继承中的对象比较

object comparison in inheriance

本文关键字:比较 对象 继承      更新时间:2023-10-16

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

 #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的地址偏移以匹配CB部分。这就是表达式(pb == &c)求值为true的原因。

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

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

该表达式的值将是false

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

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

    class C: public A, public B

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

在您的例子中,pa和pb实际上指向不同的地址,但由于比较期间的隐式转换,y被赋值为3。但是,通过对char*进行重新解释强制转换,您将带走允许编译器进行隐式强制转换的信息。相反,会进行普通的指针比较,结果为false。

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

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

将对象'c'的地址传递给类A的指针'pa';指向b类的指针'pb'

为'pa' &&'pb'保存了指向类c的对象'c'的相同内存,因此变量x的表达式&

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