2016-04-08 4 views
4

C++: Comparing pointers of base and derived classesを読んだ後、私はこれがうまくいかないと考えました。2つの異なる継承ポインタアドレスはどのように等しくなりますか?

これを実行すると、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 
+0

私はこの上の基準を知らないが、 – vu1p3n0x

+1

のdynamic_castを比較する前に、 'Bの*'に変換するために '&C 'に暗黙にはdynamic_castがあるかもしれないように見えることはexpensiすることができ実際に実行されることはありません。 – JDiMatteo

+2

"*印刷されたアドレスのほかに比較されるものは、真実になる可能性がありますか?*"静的に共通型にキャストされた後の2つのポインタ。 –

答えて

5

ポインタの等価比較c_as_b == &cは暗黙のポインタ変換を行います。 [expr.eq]から:比較が起こることができるように

If at least one of the operands is a pointer, pointer conversions (4.10), function pointer conversions (4.12), and qualification conversions (4.4) are performed on both operands to bring them to their composite pointer type (Clause 5).

基本的には、&cB*に変換されます。どちらの点では、それはc_as_bとまったく同じです(それでは、最初にそのポインタを取得した方法です)。

+0

「[expr.eq]」とは何ですか? – JDiMatteo

+0

@JDiMatteoこれはC++標準のセクション見出しです。 – Barry

1

この例では、cがBに静的にアップキャストされ、次にc_as_bと比較され、trueとなります。

-1

誰も触れていない質問の部分に答える:==結果が偽になる同様の小さな例を挙げることができますか?ここで

は偽で==結果は、dynamic_cast<void*>を使用して同様の比較が真なり、コメントアウト同様の例で、コンパイル時にエラーで==結果その方法です:

#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)