【问题标题】:Equality of pointers to classes in hierarchy指向层次结构中类的指针的相等性
【发布时间】:2014-12-15 13:31:15
【问题描述】:
#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,这表明第一个相等是正确的,第二个相等但不是第三个。由于papb 都设置为&amp;c,所以前两个是有道理的,但是为什么第三个相等是假的呢?

我在 Visual C++ 2012 中运行此代码并使用调试器检查地址:

pa == 0x003bfc90
pb == 0x003bfc98
&c == 0x003bfc90

显然,papb 不指向同一个地址,这意味着第三个相等性应该为假(确实如此)。但是为什么前两个是真的呢?你能解释一下这里发生了什么吗?

【问题讨论】:

  • 编译器会根据类型自动将偏移量添加到指针位置。您的演员可以防止这种情况发生。

标签: c++ class pointers inheritance memory-address


【解决方案1】:

这两个指针确实有不同的值,因为它们指向c的不同子对象;这两个对象必须存在于不同的位置。

没有reinterpret_cast,相等比较首先寻找到相同指针类型的合适转换。这通过修改指针值以指向cB 子对象,将&amp;cC* 转换为B*——与初始化pb 时应用的转换完全相同。转换后,两个指针的值相同,因此比较相等。

reinterpret_cast 表示应该将指针转换为目标类型而不修改其值,无论该转换是否有意义。所以,在转换之后,指针仍然有不同的值,并且比较不相等。

【讨论】:

  • reinterpret_cast 可以修改指针值,在不同指针类型有不同表示或大小的情况下。例如,我在许多机器上工作过,其中将char* 转换为int* 会修改值。 (当然,这是在 C++ 时代之前。)然而,即使它们仍然存在,这种机器今天也很少见。甚至在它们中,所有指向类类型的指针都必须使用相同的表示,因此不会改变。
猜你喜欢
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-14
相关资源
最近更新 更多