Question on dynamic binding

S

Soumen

Hi,

I've following code :

class Base {
public:
virtual void func() { std::cout << "Base" << std::endl; }
};

class Derived : public Base {
public:
void func() { std::cout << "Derived" << std::endl; }
};

class MostDerived : public Derived {
public:
void func() { std::cout << "MostDerived" << std::endl; }
};

int main(int argc, char **argv)
{
Base *pBase = 0;
Derived *pDerived = 0;
try {
pBase = new MostDerived;
pDerived = new MostDerived;

if (pBase) {
pBase->func();
delete pBase;
pBase = 0;
}
if (pDerived) {
pDerived->func();
delete pDerived;
pDerived = 0;
}
} catch (...) {
if (pBase) delete pBase;
if (pDerived) delete pDerived;
}
return 0;
}

On execution, why the o/p is
MostDerived
MostDerived

I's expecting it to be

Derived
Derived

as after Derived, it's no longer virtual ... Please clarify me the
reasons ...

I've verified it with g++ and Sun compiler ... same behavior with both
the compiler ...

Regards,
~ Soumen
 
C

Charles Bailey

Soumen said:
Hi,

I've following code :

class Base {
public:
virtual void func() { std::cout << "Base" << std::endl; }
};

class Derived : public Base {
public:
void func() { std::cout << "Derived" << std::endl; }
};

class MostDerived : public Derived {
public:
void func() { std::cout << "MostDerived" << std::endl; }
};

___ snipped main ___

as after Derived, it's no longer virtual ... Please clarify me the
reasons ...

I've verified it with g++ and Sun compiler ... same behavior with both
the compiler ...

Regards,
~ Soumen

func is a virtual function in all three classes as in the derived
classes it is a valid override of a virtual function in a base class.
See the section [class.virtual] in the standard.

Charles.
 
M

Marcus Kwok

Soumen said:
class Base {
public:
virtual void func() { std::cout << "Base" << std::endl; }
};

class Derived : public Base {
public:
void func() { std::cout << "Derived" << std::endl; }
};

class MostDerived : public Derived {
public:
void func() { std::cout << "MostDerived" << std::endl; }
};

int main(int argc, char **argv)
{
Base *pBase = 0;
Derived *pDerived = 0;
try {
pBase = new MostDerived;
pDerived = new MostDerived;

if (pBase) {
pBase->func();
delete pBase;
pBase = 0;
}
if (pDerived) {
pDerived->func();
delete pDerived;
pDerived = 0;
}
} catch (...) {
if (pBase) delete pBase;
if (pDerived) delete pDerived;
}
return 0;
}

On execution, why the o/p is
MostDerived
MostDerived

I's expecting it to be

Derived
Derived

as after Derived, it's no longer virtual ... Please clarify me the
reasons ...

Once a function is declared as virtual, it will always be virtual in any
derived classes. You cannot un-virtualize a function like that. The
presence of the 'virtual' keyword in the derived class function
declaration is optional, however some people like to include it merely
as a reminder.
 
S

Sylvester Hesp

Soumen wrote :
Hi,

I've following code :

class Base {
public:
virtual void func() { std::cout << "Base" << std::endl; }
};

class Derived : public Base {
public:
void func() { std::cout << "Derived" << std::endl; }
};

class MostDerived : public Derived {
public:
void func() { std::cout << "MostDerived" << std::endl; }
};

int main(int argc, char **argv)
{
Base *pBase = 0;
Derived *pDerived = 0;
try {
pBase = new MostDerived;
pDerived = new MostDerived;

if (pBase) {
pBase->func();
delete pBase;

That last statement yields UB, because Base doesn't have a virtual
destructor. If you plan to destroy objects via their base pointer,
always define a virtual destructor.

- Sylvester
 
S

Salt_Peter

Hi,

I've following code :

class Base {
public:
virtual void func() { std::cout << "Base" << std::endl; }

};

class Derived : public Base {
public:
void func() { std::cout << "Derived" << std::endl; }

};

class MostDerived : public Derived {
public:
void func() { std::cout << "MostDerived" << std::endl; }

};

int main(int argc, char **argv)
{
Base *pBase = 0;
Derived *pDerived = 0;
try {
pBase = new MostDerived;
pDerived = new MostDerived;

if (pBase) {
pBase->func();
delete pBase;
pBase = 0;
}
if (pDerived) {
pDerived->func();
delete pDerived;
pDerived = 0;
}
} catch (...) {
if (pBase) delete pBase;
if (pDerived) delete pDerived;
}
return 0;

}

On execution, why the o/p is
MostDerived
MostDerived

I's expecting it to be

Derived
Derived

No, its not since you've overridden the virtual function in
MostDerived.
as after Derived, it's no longer virtual ... Please clarify me the
reasons ...

This is incorrect, a virtual function is always virtual. The logic
here is that if you wanted Derived::func() to be called, then don't
override that virtual function in MostDerived or explicitly call
Derived::func() from MostDerived::func().
I've verified it with g++ and Sun compiler ... same behavior with both
the compiler ...

Regards,
~ Soumen

By the way, your Base dtor should be virtual (which would also imply
that derivative dtors will also be virtual).
delete pBase; // is a memory leak otherwise.
 
S

Soumen

No, its not since you've overridden the virtual function in
MostDerived.




This is incorrect, a virtual function is always virtual. The logic
here is that if you wanted Derived::func() to be called, then don't
override that virtual function in MostDerived or explicitly call
Derived::func() from MostDerived::func().

Thanks ... that means once at least one function in any class is
virtual, any class
derived from it start having a separate _vtable.
Now say func() wasn't virtual in Base. I made it virtual only in
Derived. So I think
there'll not be any Base::_vtable but there'll be Derived::_vtable and
MostDerived::_vtable.
Is my understanding is correct?

By the way, your Base dtor should be virtual (which would also imply
that derivative dtors will also be virtual).
delete pBase; // is a memory leak otherwise.

How could there be leak in this case? Though I admit if Base is
designed to be used as
base class, the dtr should be virtual.

Thanks again to all who clarified it.

Regards,
~ Soumen
 
V

Vineet Chawla

Thanks ... that means once at least one function in any class is
virtual, any class
derived from it start having a separate _vtable.
Now say func() wasn't virtual in Base. I made it virtual only in
Derived. So I think
there'll not be any Base::_vtable but there'll be Derived::_vtable and
MostDerived::_vtable.
Is my understanding is correct?




How could there be leak in this case? Though I admit if Base is
designed to be used as
base class, the dtr should be virtual.

Thanks again to all who clarified it.

Regards,
~ Soumen

The reason for memory leak is non virtual destructor. When you will
call delete pBase; it will just call base class destructor (as
destructor is non virtual so no polymorphism) and any memory allocated
in the derived classes will never be deallocated.

Regards
Vineet
 
P

peter koch

How could there be leak in this case? Though I admit if Base is
designed to be used as
base class, the dtr should be virtual.

A leak is only one possible outcome. The standard requires your
destructor to be virtual whenever you delete an object via a pointer
to its baseclass, causing undefined behaviour if it is not. In
practice, the result will often be a leak although it sometimes - as
in your example - just seems to work.
Normally, when a class has virtual functions you should declare the
destructor virtual. My recommendation is to always declare it so,
removing the virtual destructor in those cases where your analysis
tells you it is not needed.

/Peter
 
J

James Kanze

On May 24, 10:37 am, Soumen <[email protected]> wrote:

[...]
By the way, your Base dtor should be virtual (which would also imply
that derivative dtors will also be virtual).
delete pBase; // is a memory leak otherwise.

It's undefined behavior otherwise. In fact, I don't think I've
actually seen a case where it was a memory leak (although it's
certainly possible); I have seen core dumps because of it,
however. Most of the time, however, it works fine in all of
your tests, only to core dump dramatically when you do the demo
for your most important client. (Seriously: most of the time,
it works with single inheritance, but corrupts the free space
arena when multiple inheritance is involved, so you get some
strange error further down the road, in totally unrelated code.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top