子类型的对象在c++中使用哪个vtable

Which vtable does the object of subtype use in c++

本文关键字:vtable c++ 类型 对象      更新时间:2024-09-29

当我想执行这行代码时,它不会编译

baseArray[1]->function5(); 

但在导数3的vtable中,函数5应该指向导数1中的函数5。所以我认为它应该输出Derived1::function5((。但它似乎在基类中找到了function5((

我只是想知道Derived3继承了Derived1,为什么它仍然检查基类中是否存在被调用的函数?

请参考以下代码。谢谢你的帮助!

#include <iostream>
using namespace std;
class Base {
public:
virtual void function1();
virtual void function2();
virtual void function3() = 0;
void function4();
};
class Derived1 : public Base {
public:
void function1();
virtual void function5();
void function6();
};
class Derived2 : public Base {
public:
void function2();
void function3();
void function4();
void function5();
};
class Derived3 : public Derived1 {
public:
void function3();
};
void Base::function1(){
cout << "Base::function1()" << endl;
}
void Base::function2(){
cout << "Base::function2()" << endl;
}
void Base::function4(){
cout << "Base::function4()" << endl;
}
void Derived1::function1(){
cout << "Derived1::function1()" << endl;
}
void Derived1::function5(){
cout << "Derived1::function5()" << endl;
}
void Derived1::function6(){
cout << "Derived1::function6()" << endl;
}
void Derived2::function2(){
cout << "Derived2::function2()" << endl;
}
void Derived2::function3(){
cout << "Derived2::function3()" << endl;
}
void Derived2::function4(){
cout << "Derived2::function4()" << endl;
}
void Derived2::function5(){
cout << "Derived2::function5()" << endl;
}
void Derived3::function3(){
cout << "Derived3::function3()" << endl;
}
int main(){
Base *baseArray[] = { new Derived2, new Derived3 };
baseArray[1]->function5(); //why the code doesn't compile when I call function5() here? 
//in vtable of Derived 3, function5 should points to function5 in Derived1
//so I think it should output Derived1::function5()
dynamic_cast<Derived3*>(baseArray[1])->function5();

baseArray[1]->function6(); //same question, why it doesn't call function6 in Derived1?
//which vtable does baseArray[1] use?
dynamic_cast<Derived3*>(baseArray[1])->function6();
}

C++是一种静态类型的语言。这意味着对类型、成员、变量等的引用必须在编译时已知。

baseArray[1]->function5();baseArray[1]->function6();不编译的原因是baseArray[1]被声明为Base*,但function5()function6()不是Base的成员。就这么简单。这与vtables无关。这只是编译器如何选择在运行时实现虚拟方法调用调度的实现细节,但这不是C++标准所要求的。

编译器不知道Base*指针实际指向的是Derived3对象。这个事实要到运行时才能确定。这是多态性的一个关键特征。

要正确调用function5()function6(),您需要将Base*指针类型转换为具有您想要访问的成员的派生类型,正如您已经发现的那样。请注意,如果强制转换失败,指针上的dynamic_cast将返回nullptr,而您没有检查,例如:

// Derived1 and Derived2 are not related, but each has its own function5()...
if (Derived1 *d1 = dynamic_cast<Derived1*>(baseArray[index]))
d1->function5();
else if (Derived2 *d2 = dynamic_cast<Derived2*>(baseArray[index]))
d2->function5();

另一方面,如果您预先知道准确和正确的类型(如您的示例(,则可以使用static_cast,例如:

static_cast<Derived1*>(baseArray[index])->function5();