c++中subtype的对象使用哪个vtable
Which vtable does the object of subtype use in c++
当我要执行这行代码时,它没有编译
baseArray[1]->function5();
但是在Derived 3的vtable中,function5应该指向Derived1中的function5。所以我认为它应该输出 Derived1::function5()。但它似乎在 Base class
中找到 function5()
我只是想知道Derived3继承自Derived1,为什么它仍然检查调用的函数是否存在于Base class?
请参考以下代码。
感谢您的帮助!
#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
将 return 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();
当我要执行这行代码时,它没有编译
baseArray[1]->function5();
但是在Derived 3的vtable中,function5应该指向Derived1中的function5。所以我认为它应该输出 Derived1::function5()。但它似乎在 Base class
中找到 function5()我只是想知道Derived3继承自Derived1,为什么它仍然检查调用的函数是否存在于Base class?
请参考以下代码。 感谢您的帮助!
#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
将 return 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();