【问题标题】:Why are pA,pB,pC not equal?为什么 pA、pB、pC 不相等?
【发布时间】:2013-10-25 09:20:42
【问题描述】:

考虑以下程序

 #include<iostream>
 using namespace std;
 class ClassA
{
public:
    virtual ~ClassA(){};
    virtual void FunctionA(){};

};

class ClassB
{
 public:
    virtual void FunctionB(){};
};



class ClassC : public ClassA,public ClassB
{

};

void main()
{
    ClassC aObject;
    ClassA* pA = &aObject;
    ClassB* pB = &aObject;
    ClassC* pC = &aObject;

    cout<<"pA = "<<pA<<endl;
    cout<<"pB = "<<pB<<endl;
    cout<<"pC = "<<pC<<endl;

}

pA,pB,pC 应该相等,但结果是

pA = 0031FD90

pB = 0031FD94

pC = 0031FD90

为什么 pB = pA + 4? 当我改变时

class ClassA
{
public:
    virtual ~ClassA(){};
    virtual void FunctionA(){};

};
class ClassB
{
 public:
    virtual void FunctionB(){};
};

class ClassA
{
};

class ClassB
{
};

结果是

pA = 0030FAA3

pB = 0030FAA4

pC = 0030FAA3

pB = pA + 1?

【问题讨论】:

标签: c++ inheritance


【解决方案1】:

多重继承的对象有两个合并的子对象。我会编译器将其中一个指针指向一个内部对象。

【讨论】:

    【解决方案2】:

    C 有两个继承的子对象,因此是 A 对象和 B 对象的串联。当你有一个对象 C 时,它由一个对象 A 和一个对象 B 组成。它们不在同一个地址,这就是原因。所有三个指针都指向同一个对象,但作为不同的超类。编译器会为您进行转换,因此您不必担心。

    现在。为什么在一种情况下相差 4 而在另一种情况下相差 1?好吧,在第一种情况下,A 和 B 都有虚函数,因此每个子对象都必须有一个指向其 vtable 的指针(该表包含已解析的虚函数调用的地址)。所以在这种情况下,sizeof(A) 是 4。在第二种情况下,你没有虚函数,所以没有 vtable。但是每个子对象必须是独立可寻址的,所以编译器仍然需要为A类的子对象和B类的子对象分配不同的地址。两个地址之间的最小差异是1。但是我想知道EBO(空基类优化)在这种情况下不应该启动。

    【讨论】:

    • 可能与编译时未指定优化有关。
    【解决方案3】:

    这就是编译器的实现细节。 您遇到这种情况的原因是因为您的代码中有MI

    想想计算机如何访问ClassB中的成员,它使用偏移量来访问成员。因此,假设您在 B 类中有两个 int,它使用以下语句访问第二个 int 成员。

      *((int*)pb + 1) // this actually will be assembly generate by compiler
    

    但是如果pb指向你类中aObject的开头,这将不再起作用,因此编译器需要生成多个程序集版本来访问类继承结构中的同一个成员,并且有运行时成本。

    这就是编译器调整pb不等于pa的原因,这将使上面的代码工作,这是最简单有效的实现方式。

    这也解释了为什么pa == pc 不等于pb

    【讨论】:

      猜你喜欢
      • 2023-04-05
      • 2010-10-01
      • 1970-01-01
      • 2016-03-22
      • 1970-01-01
      • 2021-12-23
      相关资源
      最近更新 更多