Reputation: 14452
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
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
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
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
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