为什么pA,pB,pC不相等
Why are pA,pB,pC not equal?
考虑以下程序
#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 有两个继承的子对象,因此是 A 对象和 B 对象的串联。当您有一个对象 C 时,它由一个对象 A 后跟一个对象 B 组成。它们不位于同一地址,这就是原因。所有三个指针都指向同一个对象,但作为不同的超类。编译器会为您进行转换,因此您不必担心。
现在。为什么一种情况有 4 分,另一种情况有 1 分的差异?在第一种情况下,您有 A 和 B 的虚函数,因此每个子对象都必须有一个指向其 vtable 的指针(包含已解析的虚函数调用地址的表)。所以在这种情况下,sizeof(A)
是 4。在第二种情况下,您没有虚拟函数,因此没有 vtable。但是每个子对象都必须是可独立寻址的,因此编译器仍然必须为 A 类的子对象和类 B 的子对象分配不同的地址。两个地址之间的最小差值为 1。但我想知道在这种情况下是否不应该启动 EBO(空基类优化)。
这是编译器的实现细节。您遇到这种情况的原因是您的代码中有MI
。
考虑一下计算机如何访问ClassB
中的成员,它使用偏移量来访问成员。因此,假设您在类 B 中有两个 int,它使用以下语句访问第二个 int 成员。
*((int*)pb + 1) // this actually will be assembly generate by compiler
但是,如果pb
指向类中aObject
的开始,这将不再起作用,因此编译器需要生成多个程序集版本才能访问基于类继承结构的同一成员,并且具有运行时成本。
这就是为什么编译器将 pb 调整为不等于 pa,这将使上面的代码工作,这是最简单和效果的实现方式。
这也解释了为什么pa == pc
但不等于pb
。
- 两个字符串在 c++ 中不相等
- 如何以优化的方式同时迭代两个间距不相等的数组
- 是否确保 2 个连续的 std::chrono::steady_clock::now() 不相等?
- C ++相同的字符串不相等(实际上是char*)
- 在 c++ 中比较不相等数组或字符串的方法
- C++ - 空的 std::list begin() 和 end() 不相等
- 列表大小为 1,但 front() 和 back() 不相等
- C++中[不]相等运算符的求值顺序
- 2 个指针,0 字节相差但不相等
- 将不相等的线读入向量的向量
- 如何打印一个不相等的三角形
- 为什么这两个char阵列不相等
- 不(!)和不相等(!=)之间有什么区别是C
- 为什么这些C 元组不相等
- 为什么整数的地板本身不相等(CPP)
- 当使用不相等vs均等时,是否存在任何性能差异
- 为什么这两个值在 arduino 上不相等
- 字符串在相等时比较不相等
- 将字符转换为 int 会显示不相等的数字
- 为什么pA,pB,pC不相等