我正在尝试了解 C++ 代码中的多态行为。看到下面程序的输出,我感到很惊讶。
以下代码的输出我预计在以下编程语句中会出现一些编译错误/崩溃。但是这个程序的输出让我很惊讶。
p = (Class1*) &object3;
p->f();
p->g();
我不明白为什么。我正在使用 Visual Studio 2008。
代码片段。
#include "stdafx.h"
#include <iostream>
using namespace std;
class Class1
{
public:
virtual void f()
{
cout << "Function f() in Class1\n";
}
void g()
{
cout << "Function g() in Class1\n";
}
};
class Class2
{
public:
virtual void f()
{
cout << "Function f() in Class2\n";
}
void g()
{
cout << "Function g() in Class2\n";
}
};
class Class3
{
public:
virtual void h()
{
cout << "Function h() in Class3\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
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();
p->g();
//p->h(); Compilation error
return 0;
}
O/P:
Class1 中的函数 f()
Class1 中的函数 g()
Class2 中的函数 f()
Class1 中的函数 g()
Class3 中的函数 h()
Class1 中的函数 g()
最佳答案
你正在使用一个邪恶的 C 风格转换,在这种情况下相当于 reinterpret_cast
,将一个指针指向一个类并假装它指向一个不相关的类。
I was expecting some compilation error/crash
没有编译错误,因为你故意阻止编译器检查类型转换 - 这就是 reinterpret_cast
的目的,也是避免它的原因(C 风格的转换更是如此)所以)除非真的有必要。可能会发生崩溃或任何其他类型的未定义运行时行为。
在您的情况下,类布局似乎足够相似,即使指针类型完全错误,虚函数调用也能成功。这并不奇怪,因为您的类定义都非常相似;但这在很大程度上不是保证的行为,原则上它可能会以许多灾难性的方式失败。
如果你想要多态行为,那么 Class2
和 Class3
应该继承自 Class1
。指针转换将在没有转换的情况下有效,并且多态行为将得到很好的定义 - f()
将根据对象类型进行虚拟分派(dispatch),而 g()
根据指针类型非虚拟。
关于c++ - Visual Studio 2008 : Polymorphic behavior of C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14941723/