继承中的对象比较

object comparison in inheriance

在下面的代码中,使用 == 比较两个对象显示的输出与比较两个字符指针不同。请帮助我了解它是如何工作的。

 #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;
  }

输出: 136

为什么 y 的值为 3 而 z 的值为 6。这里到底发生了什么。
欢迎任何意见。

const int y = (pb == &c) ? 3 : 4;

相当于使用

B *pb2 = &c;
const int y = (pb == bp2) ? 3 : 4;

&cB* 比较时,它会自动转换为 B*,这会偏移 c 的地址以匹配 B C 的一部分。这就是表达式 (pb == &c) 的计算结果为 true.

的原因

但是,papb是不同的地址。因此,当您使用

比较它们的值时
(reinterpret_cast<char*>(pa) ==   reinterpret_cast<char*>(pb))

该表达式的值将是 false

您将对象 'c' 的地址传递给 class A 的指针 'pa' & 传递给 class B 的指针 'pb'。

由于 'pa' && 'pb' 拥有引用 Class C 的对象 'c' 的相同内存,因此变量 x & y 的表达式为真。

对于 z 变量的表达式,您将 'pa' 的地址与 'pb' 的地址进行比较,迫使它们解释为强制转换的字符指针,但这两个指针可能已分配在内存中的两个不同位置,因此它们不匹配,你会得到 z=6(即 false)

您正在使用多重继承。在这种情况下,当您创建 Derived class 的实例时,通常会发生以下情况:

  • 保留了足够的内存来保存所有基础 class 和派生 class 的数据。
  • baseclasses的数据在内存中的布局顺序就是你为Derivedclass指定的继承顺序。对于您的情况:

    class C: public A, public B

    对象的内存布局如下:A 数据成员,B 数据成员,然后是 C 数据成员。

在你的例子中,pa 和 pb 实际上指向不同的地址,但是由于比较期间的隐式转换,y 被赋予了值 3。但是通过将 reinterpret cast 转换为 char* ,您将带走允许编译器进行隐式转换的信息。取而代之的是进行简单的指针比较,结果为假。

如果你这样做 C* pc = &c;

并在调试器中检查 pc 的值,您会注意到它与突出显示上述点的 pa 相同。