尊敬的先生!
我应该告诉你我所知道的和我不知道的问题,以便你能解决我理解的薄弱环节.
我知道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的作用是什么以及如何运作请详细说明.
由于在类中show声明,编译器不会像对非虚方法那样对方法调用进行硬编码,而是在V表中编译查找以便检索正确的函数.virtualperson
因此ptr->show()将编译为ptr->vtable['show']()"搜索与方法对应的函数指针show并执行它".
由于在运行时ptr指向类的对象teacher,因此vtable槽show包含指向show类中方法的指针teacher.这就是执行正确方法的原因.
实际上,V表中的查找不是使用字符串,而是使用数字方法标识符,以便尽可能快.
我想你应该提请注意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).
| 归档时间: |
|
| 查看次数: |
5074 次 |
| 最近记录: |