我对将基类对象的指针转换为派生类的指针感到困惑。 请检查以下代码:
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
结果是:
任何人都可以帮我解释为什么d1->print()
打印“我是基础中的虚函数。”?
#include <iostream>
using namespace std;
class base
{
public:
virtual void print()
{
cout << "I'm a virtual function in base." << endl;
}
};
class derivate_class : public base
{
public:
void print()
{
cout << "I rewrite the virtual function in base." << endl;
}
void print1()
{
cout << "I'm a function in derivate class." << endl;
}
};
int main()
{
base* b = new base();
derivate_class *d = new derivate_class();
b->print();
d->print1();
base* cb = b;
b = d;
b->print();
cout << "*********************" << endl;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
system("pause");
return 0;
}
答案 0 :(得分:2)
这是UB,所以任何事情都可能发生。
但是这里有一个解释:d1
实际上并不指向derivate_class
,而是指向base
。
base* b = new base();
//...
base* cb = b;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
调用是动态解决的,因为它是通过指针而方法是virtual
。
print1
不是virtual
,因此呼叫会静态解决。 print
但是virtual
,因此调用了派生类型最多的实现。但在这种情况下,派生最多的类型实际上是base
。
在幕后,在print
中的vfptr指向的虚拟函数表中查找方法cb
。由于cv
是base
,因此该表将是base
的表,其中包含具有print
实现的函数base::print
。这就是为什么这个函数被调用了。
答案 1 :(得分:0)
d1是一个derivate_class指针,但它实际指向的数据(cb)是base类型。由于print()是虚拟的,因此动态解析调用,因此它将在虚函数表中找到base的实现而不是derivate_class。