【问题标题】:How are two different inherited pointer addresses equal?两个不同的继承指针地址如何相等?
【发布时间】:2016-04-08 19:12:48
【问题描述】:

阅读C++: Comparing pointers of base and derived classes 后,我认为这肯定行不通。

当我执行此操作时,c_as_b&c 的打印地址不同,那么为什么此打印“在比较同一层次结构中的指针似乎是安全的”?除了打印的地址之外,还有什么比较可能导致真实?

你能举一个==导致错误的类似小例子吗?

#include <iostream>
using namespace std;

struct A { std::string s; };
struct B { int i; };
struct C : A, B { double d; };

int main() {
    C c;
    B* c_as_b = &c;
    A* c_as_a = &c;
    cout << "c_as_a: " << c_as_a << endl
         << "c_as_b: " << c_as_b << endl
         << "&c:     " << &c << endl;
    cout << (c_as_b == &c ? "seems safe to compare pointers in same hierarchy" : "definately not safe") << endl;
    return 0;
}

样本输出:

c_as_a: 0xbfb98f10
c_as_b: 0xbfb98f14
&c:     0xbfb98f10
seems safe to compare pointers in same hierarchy

【问题讨论】:

  • 我不知道这方面的标准,但看起来&amp;c 上可能有一个隐含的dynamic_cast,以便在比较之前将其转换为B*
  • dynamic_cast 可能很昂贵,并且永远不会隐式完成
  • "除了打印出来的地址外,还有什么比较可能为真?" 两个指针被静态转换为通用类型后。
  • @vu1p3n0x,这里不能动态转换,没有虚函数。
  • @EdHeal 嗯,与其他类型的石膏相比,它的价格昂贵。

标签: c++ pointers inheritance


【解决方案1】:

指针相等比较c_as_b == &amp;c 将进行隐式指针转换。来自 [expr.eq]:

如果至少有一个操作数是指针,指针转换(4.10),函数指针转换(4.12), 和限定转换 (4.4) 对两个操作数执行以将它们带到它们的复合指针 类型(第 5 条)。

基本上,&amp;c 将转换为 B*,以便进行比较。在这一点上,它与c_as_b 完全相同(因为这就是您获得该指针的方式),因此它们比较相等。

【讨论】:

  • 什么是“[expr.eq]”?
  • @JDiMatteo 这是 C++ 标准中的章节标题。
【解决方案2】:

在此示例中,c 静态向上转换为 B,然后与 c_as_b 进行比较得出 true。

【讨论】:

    【解决方案3】:

    回答没有人提到的部分问题:你能举一个类似的小例子,其中 == 导致错误吗?

    这是一个类似的示例,其中== 导致错误,使用dynamic_cast&lt;void*&gt; 使相同的比较正确,并且注释掉是== 导致编译时错误的一种方式:

    #include <iostream>
    using namespace std;
    
    struct A { virtual ~A() {} };
    struct B : A { };
    struct C : A { };
    struct D : B, C { };
    
    int main() {
        D d;
        C* c = &d;
        B* b = &d;
        A* a_through_b = b; // &d results in error: 'A' is an ambiguous base of 'D'
        A* a_through_c = c;
        cout << "&d:           " << &d << endl
             << "c :           " << c << endl
             << "b :           " << b << endl
             << "a_through_b : " << a_through_b << endl
             << "a_through_c : " << a_through_c << endl;
        cout << (a_through_b == a_through_c ? "a_through_b == a_through_c" : "a_through_b != a_through_c") << endl;
        cout << (dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c) ? "dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c)" : "dynamic_cast<void*>(a_through_b) != dynamic_cast<void*>(a_through_c)") << endl;
        //cout << (a_through_c == &d) << endl; // error: 'A' is an ambiguous base of 'D'
        cout << (dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d) ? "dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d)" : "dynamic_cast<void*>(a_through_c) != dynamic_cast<void*>(&d)") << endl;
        return 0;
    }
    

    样本输出:

    &d:           0xbff6d558
    c :           0xbff6d55c
    b :           0xbff6d558
    a_through_b : 0xbff6d558
    a_through_c : 0xbff6d55c
    a_through_b != a_through_c
    dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c)
    dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d)
    

    【讨论】:

      猜你喜欢
      • 2015-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-10
      • 1970-01-01
      相关资源
      最近更新 更多