为什么在C ++中添加虚拟关键字后此指针值发生了变化

问题描述 投票:0回答:1

考虑下面的代码行

#include<iostream>
using namespace std;

class base
{
int i;
public:
void printb()
{
cout << "This pointer of base   "<<this<<endl;
}
};

class derived: public base
{
int i;
public:
void printd()
{
cout << "This pointer of derived "<<this<<endl;
}
};

main()
{

derived d1;
d1.printd();
d1.printb();
}

在64位ubuntu机器上用g ++(4.8.4)编译后得到的结果是

This pointer of derived 0x7ffe74697ac0
This pointer of base    0x7ffe74697ac0

根据我的理解,base和derived这个指针都是相同的,因为我们用单个对象调用。我将virtual关键字添加到派生类的printd()函数中,如下所示

#include<iostream>
using namespace std;

class base
{
int i;
public:
void printb()
{
cout << "This pointer of base   "<<this<<endl;
}
};

class derived: public base
{
int i;
public:
virtual void printd()
{
cout << "This pointer of derived "<<this<<endl;
}
};

main()
{

derived d1;
d1.printd();
d1.printb();
}

上述代码的输出如下

This pointer of derived 0x7ffee969b1d0
This pointer of base    0x7ffee969b1d8

这里的指针值在derived和base中是不同的,即使用单个对象调用。每次运行程序时,派生此指针和基于此指针之间存在1byte的差异。任何人都可以告诉为什么这个指针的差异以及虚拟关键字如何影响这个指针。

c++ this
1个回答
4
投票

通过添加virtual关键字,您使derived多态。运行时多态性的常见实现是添加指向对象开头的指针。此vptr指向动态调度的函数表(通常称为vtable)。

因此,base子对象(不是多态的)通过隐藏指针在derived超级对象内部偏移。

您会看到指针自动调整,因为编译器会在调用成员函数时注入代码以执行此调整。这样可以确保printb能够在正确的位置访问base的所有(潜在)成员。

© www.soinside.com 2019 - 2024. All rights reserved.