2012-03-30 49 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

相关问题