C ++基类指针调用子虚函数,为什么基类指针可以看到子类成员 [英] C++ base class pointer calls child virtual function, why could base class pointer see child class member

查看:144
本文介绍了C ++基类指针调用子虚函数,为什么基类指针可以看到子类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我可能会感到困惑.我知道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().

当我声明两个类对象basechild时,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*类型如何看到课? (基本值为2?).当我调用base_array[1]->print()时,base_array[1]的类型为Base*,但是在运行时它发现它将使用Childprint().但是,我很困惑为什么在这段时间内可以访问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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆