abyss.7
abyss.7

Reputation: 14452

When can I compare pointers to the same object in c++?

For example, I have some class hierarchy (possibly, with all kinds of inheritance - public, private, public virtual, multi-inheritance, etc.):

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; };

Using casts I get pointers to every sub-object of the main "big" object:

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

What pairs of these pointers may I compare for equality (operator==) and why? Will the comparison use delta-logic or some other technique?

What are the possible situations, when I can't compare pointers to the same complex object? What kind of object it can be?

I expect, that all of the pointers to the same object are always equal.

Upvotes: 5

Views: 1213

Answers (4)

user396672
user396672

Reputation: 3166

Generally, to ensure that two pointers (possibly of diffrent type) point to the same object, use

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

Of course, both pointer types should be polimorphic to provide correct dynamic_cast

If the class hierarchy has a single (possibly virtual) root, it's possible to cast both poiners to pointers to the root class and then compare two results (without dynamic casting)

Upvotes: 1

Vaughn Cato
Vaughn Cato

Reputation: 64308

You have to be careful here. For example, c and e are pointers to distinct aspects of *f, and therefore are not really the same object. Fortunately the compiler will give you an error if you try to compare c and e because one is not derived from the other. Any other comparison in your example will work because one of the pointers can be trivially converted to the type of the other.

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
}

Upvotes: 3

Mike Seymour
Mike Seymour

Reputation: 254431

You can compare two pointers if one pointer type is implicitly convertible to the other; that is, if they both point to the same type, or one points to a base class of the other's. The conversion will make the necessary adjustment to the address so that, if both pointers point to the same object, they will compare equal.

In this case, you can compare any pair except c == e, since neither of C nor E is derived from the other. To compare those, you would either need to cross-cast, or to convert both to their common base class; neither of these can be done implicitly.

By the way, there's no need for dynamic_cast in your code, since you're casting to base class pointers and that safe conversion can be done implicitly.

Upvotes: 3

IronMensan
IronMensan

Reputation: 6821

You can only compare pointers of the same type. However, you don't always need an explicit cast to do so. In the simple case:

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

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

When you get to more complex classes, you will need to add explicit casts so

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) {}

Upvotes: 0

Related Questions