2012-03-30 99 views
5

例如,我有一些類層次(可能的話,有各類繼承 - 公共,私有,公有虛,多繼承等):什麼時候可以比較指向C++中相同對象的指針?

class A { 
    int a; 
public: 
    virtual ~A() {} 
}; 

class B: public A { int b; }; 
class C: public virtual B { int c; }; 
class E: public virtual B { int e; }; 
class F: public C, public E { int f; }; 

使用強制轉換,我得到的指針每分主要「大」對象的對象:

F * f = new F; 
E * e = f; 
C * c = f; 
B * b = f; 
A * a = f; 

這兩個指針可以用來比較相等性(operator ==)和爲什麼? 比較會使用增量邏輯還是其他技術?

當我無法比較指向同一個複雜對象的指針時,有什麼可能的情況? 它可以是什麼樣的對象?

我想,所有指向同一對象的指針總是相等的。

+1

*爲什麼要比較它們,這就是問題。 – Jon 2012-03-30 12:49:03

+3

指針只是地址,如果你想比較任何東西,它可以是指針指向的對象,你不能比較兩個地址,並判斷這些位置上的對象是否相等。很好,錯誤......你可以。 ..但那是錯誤的。 – 2012-03-30 12:51:17

+0

@Als:如果我做了'std :: cout <<(e == b)<<「」<< e <<「」<< b << std :: endl;',它會打印'1 0x1aaa020 0x1aaa030' 。所以地址是不同的,但指針是平等的。整個問題是關於這種比較的常見C++規則。 – 2012-03-30 12:58:50

回答

3

您可以比較兩個指針,如果一個指針類型隱式轉換爲其他;也就是說,如果它們都指向相同的類型,或者一個指向另一個的基類。轉換將對地址進行必要的調整,以便如果兩個指針指向相同的對象,則它們將相等。

在這種情況下,您可以比較除c == e以外的任何一對,因爲CE都不是從另一個派生的。爲了比較這些,你需要交叉演奏,或者將它們轉換爲共同的基類;這些都可以隱含地完成。

順便說一下,在代碼中不需要dynamic_cast,因爲您正在轉換爲基類指針,並且安全轉換可以隱式完成。

3

你必須在這裏小心。例如,c和e是指向* f的不同方面的指針,因此不是真正的同一個對象。幸運的是,如果您嘗試比較c和e,編譯器會給您一個錯誤,因爲一個不是從另一個派生的。您的示例中的任何其他比較都可以工作,因爲其中一個指針可以簡單地轉換爲另一個指針的類型。

class A { 
    int a; 
public: 
    virtual ~A() {} 
}; 

class B: public A { int b; }; 
class C: public virtual B { int c; }; 
class E: public virtual B { int e; }; 
class F: public C, public E { int f; }; 

{ 
    F * f = new F; 
    E * e = dynamic_cast<E*>(f); 
    C * c = dynamic_cast<C*>(f); 
    B * b = dynamic_cast<B*>(f); 
    A * a = dynamic_cast<A*>(f); 
    cerr << (a==b) << "\n"; // true 
    cerr << (a==c) << "\n"; // true 
    cerr << (a==e) << "\n"; // true 
    cerr << (a==f) << "\n"; // true 
    cerr << (b==c) << "\n"; // true 
    cerr << (b==e) << "\n"; // true 
    cerr << (b==f) << "\n"; // true 
    cerr << (c==e) << "\n"; // compile error 
    cerr << (c==f) << "\n"; // true 
    cerr << (e==f) << "\n"; // true 
} 
0

您只能比較相同類型的指針。但是,您並不總是需要明確的演員才能這樣做。在簡單情況下:

B * pB = new B(); 
A * pA = pB; 

if (pA == pB) {} //pB is implicitly cast to an A * 

當你到更復雜的類,您將需要增加明確蒙上所以

F * pF = new F(); 
C * pC = dynamic_cast<C *>(pF) 
A * pA1 = dynamic_cast<A *>(pF); 
A * pA2 = dynamic_cast<A *>(pC); 

//should all be true 
if (pF == dynamic_cast<F *>(pA)) {} 
if (pA1 == dynamic_cast<A *>(pF)) {} 
if (pA1 == pA2) {} 
1

通常,爲了確保兩個指針(可能的不同勢型)指向相同的對象,使用

dynamic_cast<void*>(pointer1) == dynamic_cast<void*>(pointer2) 

當然,兩個指針類型應該是polimorphic提供正確的dynamic_cast

如果類層次結構有一個(可能是虛擬的)根,可以將兩個poiners轉換爲指向根類的指針,然後比較兩個結果(不帶動態轉換)

+0

@Konrad:爲什麼沒有意義?如果向兩個指針的向下轉換都使用相同的地址,那麼它們指向相同的對象(反之亦然)。如果指針類型不能相互轉換(或某些根類),我不知道其他方式來檢查它,除了dynamic_cast(儘管可能不是OP的問題) – user396672 2012-03-30 15:30:45

+0

@Konrad:我的代碼檢查(向下)轉到大多數派生類是指同一個對象(我不假裝這嚴格地回答了OP的問題) – user396672 2012-03-30 16:12:27

+0

在閱讀標準(由新問題提示)之後,我將所有內容背部。我沒有意識到(而且非常可怕的是相反),該標準在'dynamic_cast'中爲(cv qualified)'void *'額外提供了條款。 – 2012-04-02 10:30:08

相關問題