C++ simple polymorphism issue
Ok I admit it, I'm a total C++ noob.
I was checking the book Data Structures and algorithms in C++ by Adam Drozdek, in the section 1.5 : "Polymorphism" he proposes the next example:
class Class1
{
public:
virtual void f()
{
cout << "Function f() in Class1" << endl;
}
void g()
{
cout << "Function g() in Class1" << endl;
}
};
class Class2
{
public:
virtual void f()
{
cout << "Function 开发者_Go百科f() in Class2" << endl;
}
void g()
{
cout << "Function g() in Class2" << endl;
}
};
class Class3
{
public:
virtual void h()
{
cout << "Function h() in Class3" << endl;
}
};
int main()
{
Class1 object1, *p;
Class2 object2;
Class3 object3;
p = &object1;
p->f();
p->g();
p = (Class1*)&object2;
p->f();
p->g();
p = (Class1*)&object3;
p->f(); // Abnormal program termination should occur here since there is
// no f() method in object3, instead object3->h() is called
p->g();
//p->h(); h() is not a member of Class1
return 0;
}
I compiled this using Visual Studio 2010, and two things happened:
- First there was no "abnormal termination" in the line
p->f()
- The method
h()
of object3 is called in the line where the "abnormal termination" should occur.
The output of the programs is:
Function f() in Class1 Function g() in Class1 Function f() in Class2 Function g() in Class1 Function h() in Class3 Function g() in Class1
I´m trying to understand why this happens, but it seems too strange for me.
Any help would be great.
Thanks in advance!
If that's really the code the book uses, throw the book in the trash immediately. Polymorphism works over inheritance, such as
class Class2 : public Class1
Without that, there is no hope of a correct program.
The author appears to try and circumvent the requirement (i.e., get an incorrect program to compile) by using
p = (Class1*)&object2;
This is a C-style cast, and it is interpreted as the C++
p = reinterpret_cast< Class1 * >( &object2 );
reinterpret_cast
is a dangerous operator, and should never be used between two polymorphic types. This is what should be used:
// use only if dynamic type of object2 is same as static type:
p = static_cast< Class1 * >( &object2 );
// Will not compile unless you add : public Class1
or
// returns NULL if object2 dynamic type not derived from Class1
p = dynamic_cast< Class1 * >( &object2 );
As for the "abnormal termination", I think the author was describing how the code crashed on his machine. However, that's not because the language says it should. He just wrote an incorrect program, which may crash on some machines but not others.
h()
is probably in the same position in the vtable for Class3 that f()
is for Class1 and Class2. The vtable is a table that is stored in your object that contains the addresses of virtual methods, so that the runtime can call the right method even from a pointer of a different type.
This is a weird example without any inheritance. Casts like this aren't exactly safe and I doubt this is portable.
Compiler did a compile time binding to the first element of virtual table, since p was of type Class1 it sees that it got method f(). But when actually you run the program it actually gets handle to h() whose address is stored in first position in virtual table.
- I think this is implementation dependent.
This example is abominable and should never have appeared in print. It is not an example of polymorphism.
By casting the objects to unrelated class pointers, he's invoking undefined behavior. Since it's undefined, it's not at all surprising that you get different results than he does.
精彩评论