C ++基类指针调用子虚函数,为什么基类指针可以看到子类成员 [英] C++ base class pointer calls child virtual function, why could base class pointer see child class member
问题描述
我想我可能会感到困惑.我知道C ++中具有虚函数的类具有一个vtable(每个类类型一个vtable),因此Base
类的vtable将具有一个元素&Base::print()
,而Child
类的vtable将具有一个元素&Child::print()
.
I think I might be confusing myself. I know class with virtual functions in C++ has a vtable (one vtable per class type), so the vtable of Base
class will have one element &Base::print()
, while the vtable of Child
class will have one element &Child::print()
.
当我声明两个类对象base
和child
时,base
的vtable_ptr将指向Base
类的vtable,而child
的vtable_ptr将指向Child
类的vtable.之后,我将base和child的地址分配给Base类型指针的数组.我叫base_array[0]->print()
和base_array[1]->print()
.我的问题是,在运行时base_array[0]
和base_array[1]
的类型均为Base*
,尽管v表查找将提供正确的函数指针,但Base*
类型如何看到base_array[1]->print()
时,base_array[1]
的类型为Base*
,但是在运行时它发现它将使用Child
类print()
.但是,我很困惑为什么在这段时间内可以访问value2
,因为我正在玩Base*
.....我想我必须在某处错过某些东西.
When I declare my two class objects, base
and child
, base
's vtable_ptr will pointer to Base
class's vtable, while child
's vtable_ptr will point to Child
class's vtable. After I assign the address of base and child to an array of Base type pointer. I call base_array[0]->print()
and base_array[1]->print()
. My question is, both base_array[0]
and base_array[1]
is of type Base*
, during run-time, although the v-table lookup will gives the correct function pointer, how could a Base*
type see the element in Child
class? (basically value 2?). When I call base_array[1]->print()
, base_array[1]
is of type Base*
, but during run time it finds out it will use Child
class print()
. However, I am confused why value2
can be accessed during this time, because I am playing with type Base*
..... I think I must miss something somewhere.
#include "iostream"
#include <string>
using namespace std;
class Base {
public:
int value;
string name;
Base(int _value, string _name) : value(_value),name(_name) {
}
virtual void print() {
cout << "name is " << name << " value is " << value << endl;
}
};
class Child : public Base{
public:
int value2;
Child(int _value, string _name, int _value2): Base(_value,_name), value2(_value2) {
}
virtual void print() {
cout << "name is " << name << " value is " << value << " value2 is " << value2 << endl;
}
};
int main()
{
Base base = Base(10,"base");
Child child = Child(11,"child",22);
Base* base_array[2];
base_array[0] = &base;
base_array[1] = &child;
base_array[0]->print();
base_array[1]->print();
return 0;
}
推荐答案
通过指针对print
的调用会执行vtable查找,以确定要调用的实际函数.
The call to print
through the pointer does a vtable lookup to determine what actual function to call.
该函数知道'this'参数的实际类型.
The function knows the actual type of the 'this' argument.
编译器还将插入代码以调整参数的实际类型(例如,您拥有class child:
The compiler will also insert code to adjust to the actual type of the argument (say you have class child:
public base1, public base2 { void print(); };
其中,print
是从base2
继承的虚拟成员.在这种情况下,相关的vtable不会在child中处于偏移量0,因此需要进行调整才能从存储的指针值转换为正确的对象位置.
where print
is a virtual member inherited from base2
. In that case the relevant vtable will not be at offset 0 in child so an adjustment will be needed to translate from the stored pointer value to the correct object location).
修复所需的数据通常存储为隐藏的运行时类型信息(RTTI)块的一部分.
The data needed for that fix-up is generally stored as part of hidden run-time type information (RTTI) blocks.
这篇关于C ++基类指针调用子虚函数,为什么基类指针可以看到子类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!