C++ 内在的客体比较

C++ 内在的客体比较,c++,operators,C++,Operators,在下面的代码中,使用==比较两个对象与比较两个字符指针显示不同的输出。请帮助我了解它的工作原理 #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

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

 #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;
  }
#包括
甲级
{
公众:
A():m_i(0){}
受保护的:
国际货币基金组织;
};
B类
{
公众:
B():mud(0.0){}
受保护的:
双m_d;
};
C类
:公众A
,公共图书馆
{
公众:
C():m_C('a'){}
私人:
charm_c;
};
int main()
{
C C;
A*pa=&c;
B*pb=&c;
常数int x=(pa==&c)?1:2;
常数y=(pb==&c)?3:4;
const int z=(重新解释铸造(pa)=重新解释铸造(pb))?5:6;
标准::cout
相当于使用

B *pb2 = &c;
const int y = (pb == bp2) ? 3 : 4;
当将
&c
B*
进行比较时,它会自动转换为
B*
,这会偏移
c
的地址,以匹配
c
B
部分。这就是表达式
(pb=&c)
计算结果为
true
的原因

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

(reinterpret_cast<char*>(pa) ==   reinterpret_cast<char*>(pb))
(重新解释投射(pa)=重新解释投射(pb))
该表达式的值将为
false

相当于使用

B *pb2 = &c;
const int y = (pb == bp2) ? 3 : 4;
当将
&c
B*
进行比较时,它会自动转换为
B*
,这会偏移
c
的地址,以匹配
c
B
部分。这就是表达式
(pb=&c)
计算结果为
true
的原因

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

(reinterpret_cast<char*>(pa) ==   reinterpret_cast<char*>(pb))
(重新解释投射(pa)=重新解释投射(pb))

如果将对象“c”的地址传递给类A的指针“pa”和类B的指针“pb”,则该表达式的值将为
false

由于“pa”和“pb”拥有与类c的对象“c”引用的相同内存,所以变量x&y的表达式为true


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

将对象“c”的地址传递给类a的指针“pa”和类B的指针“pb”

由于“pa”和“pb”拥有与类c的对象“c”引用的相同内存,所以变量x&y的表达式为true


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

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

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

    C类:公共A、公共B

    对象的内存布局如下所示:A数据成员、B数据成员和C数据成员

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

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


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

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

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

    C类:公共A、公共B

    对象的内存布局如下所示:A数据成员、B数据成员和C数据成员

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

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


在debugger中检查pc的值,您会注意到它与pa相同,这突出了上面的一点。

谢谢您的输入。请尝试打印pa、pb和c的地址。我认为pa和pb不一样。这就是我所说的,pa和pb在不同的位置有不同的地址和c,但值存储在指针pa和pb中引用相同的地址,即c的地址。因此,第一个和第二个表达式为真,而第三个表达式为假。存储在pa和pb中的值是不同的。@Saravanan,你不明白。看,pa和pb是两个指针,它们在物理位置(即c的地址)中存储了相同的值。但它们也存储在不同的位置ons。谢谢您的输入。请尝试打印pa、pb和c的地址。我认为pa和pb不一样。这就是我所说的,pa和pb在不同的位置有不同的地址和c,但指针pa和pb中存储的值指的是相同的地址,即c的地址。因此,第一个和第二个表达式为真,而第三个表达式为假值在这里,pa和pb是不同的。@Saravanan,你不明白。看,pa和pb是两个指针,它们的物理位置(即c的地址)中存储了相同的值。但它们都是