c ++如何在内部实现多态?

Zia*_*man 7 c++ oop

尊敬的先生!

我应该告诉你我所知道的和我不知道的问题,以便你能解决我理解的薄弱环节.

我知道c ++通过使用Vtable来实现多态性,Vtable是指针数组,每个指针指向类的虚函数,层次结构中的每个类都有一个vtable.现在假设我有以下课程

class person
{
    char name[20];
public:
    person(char* pname)
    {
        strcpy(name,pname);
    }

    virtual void show()
    {
        cout<<"inside person show method, Name: "<<name;
    }
};

class teacher:public person
{
     int scale;

     teacher(char*pname, int s):person(pname)
     {
         scale=s;
     }

     void show()
     {
         cout<<"inside the teacher show method, Scale: "<<scale;
     }
};
Run Code Online (Sandbox Code Playgroud)

现在假设我在主程序中写道

person *ptr;
ptr=new teacher(16,"Zia");
ptr->show();
Run Code Online (Sandbox Code Playgroud)

现在我很困惑,此时调用将转到基类的show函数,现在因为它是一个虚函数,因此它会调用approprite函数.我知道我错了.我很困惑,这将是一系列的电话.Vtable的作用是什么以及如何运作请详细说明.

Vin*_*ert 9

由于在类中show声明,编译器不会像对非虚方法那样对方法调用进行硬编码,而是在V表中编译查找以便检索正确的函数.virtualperson

因此ptr->show()将编译为ptr->vtable['show']()"搜索与方法对应的函数指针show并执行它".

由于在运行时ptr指向类的对象teacher,因此vtable槽show包含指向show类中方法的指针teacher.这就是执行正确方法的原因.

实际上,V表中的查找不是使用字符串,而是使用数字方法标识符,以便尽可能快.


Ser*_*kov 8

我想你应该提请注意Stanley B. Lippman的书" Inside C++ object model ".

让我们为您的课程寻找内部演示:

人和老师的虚拟表

|---------------|  +---> |------------------------|
|  name         |  |     | "type_info" for person |
|---------------|  |     |------------------------|
|__vptr__person |--+     | "person::~person"      |
|---------------|        |------------------------|
person p;                | "person::show"         |
                         |------------------------|

|----------------|  +---> |-------------------------|
|person subobject|  |     | "type_info" for teacher |
|----------------|  |     |-------------------------|
|__vptr__teacher |--+     | "teacher::~teacher"     |
|----------------|        |-------------------------|
teacher t;                | "teacher::show"         |
                          |-------------------------|               
Run Code Online (Sandbox Code Playgroud)

通常,我们不知道每次调用show()时对象ptr地址的确切类型.但是,我们知道通过ptr我们可以访问与对象类关联的虚拟表.

虽然我们不知道要调用哪个show()实例,但我们知道每个实例的地址都包含在插槽2中.

此信息允许编译器在内部将调用转换为

( *ptr->vptr[ 2 ] )( ptr ); 
Run Code Online (Sandbox Code Playgroud)

在此转换中,vptr表示在每个类对象中插入的内部生成的虚拟表指针,2表示与Point层次结构关联的虚拟表中的show()分配的插槽.我们在运行时唯一需要做的就是使用RTTI计算ptr的动态类型(和适当的vtable).


Nic*_*kis 6

C++语言不定义多态实现,甚至不定义vtable.这取决于编译器.
一个可能的实现是Vincent Robert提到的那个.