有人问我这个面试问题,但我弄错了。 “输出是什么”:我的答案是 135,实际输出是 136。这意味着指向两个父类的指针不相等,即使它们通过了与子类相等的先前测试。 我以为我理解 c++ 指针,但这让我很难解释。虽然我想我知道发生了什么,但我不知道为什么。任何可以提供技术解释的c++专家吗? 看起来前两个比较在本质上更合乎逻辑,而最后一个比较更文字......
#include <iostream>
class A
{
public:
A() : m_i(0) { }
protected:
int m_i;
};
class B
{
public:
B() : m_d(0.0) { }
protected:
double m_d;
};
class C
: public A, public B
{
public:
C() : m_c('a') { }
private:
char m_c;
};
int main()
{
C c;
A *pa = &c;
B *pb = &c;
const int x = (pa == &c) ? 1 : 2;
const int y = (pb == &c) ? 3 : 4;
const int z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) ? 5 : 6;
std::cout << x << y << z << std::endl;
return 0;
}
最佳答案
也许如果你打印出 pa
和 pb
会更清楚发生了什么。
std::cout << "A: " << pa << std::endl;
std::cout << "B: " << pb << std::endl;
std::cout << "C: " << &c << std::endl;
在 main
的末尾运行它给了我
A: 0xbfef54e0
B: 0xbfef54e4
C: 0xbfef54e0
(您的输出可能不同,重要的是它们并不完全相同)
这是因为 C
对象在内存中的表示方式。由于 C
既是 A
又是 B
,因此它需要具有来自每个部分的数据成员。 C
的真正布局是这样的(忽略填充):
int A::m_i;
double B::m_d;
char C::m_c;
当您将 C*
转换为 A*
时,编译器知道 A
部分从偏移量 0 开始,因此指针值不变。对于 C*
到 B*
它需要偏移 sizeof(int)
(加上填充)。此偏移处理是自动为您计算 x
和 y
完成的。对于 z
它被绕过,因为你使用 reinterpret_cast
关于c++ - 理解 C++ 指向父类/基类的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36455992/