From: jimad@microsoft.com (Jim Adcock)
Subject: Re: Must derived class reserve space for an empty base class?
Date: 30 Dec 92 19:26:35 GMT
Organization: Microsoft Corporation

In article <24490@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
|jimad@microsoft.com (Jim Adcock @ Microsoft Corporation) writes
|
| > Below find an example that frequently catches programmers off guard.
| > Again, C++ pointers DO NOT model any notion of object identity.  If you
| > want your objects to maintain a notion of object identity [A good
| > idea, IMHO] then you must explicitly GIVE your objects a notion of object
| > identity.  C++ comes with no such notion built-in.
| > 
| > #include <iostream.h>
| > 
| > class A { char bsPadding; };
| > class B : public A {};
| > class C : public A {};
| > class D : public B, public C {};
| > 
| > main()
| > {
| > 	D d;
| > 
| > 	B* pb = &d;
| > 	C* pc = &d;
| > 	A* pa1 = pb; 
| > 	A* pa2 = pc; 
| > 
| > 	if (pa1 == pa2)
| > 		cout << "pointers match\n";
| > 	else 
| > 		cout << "pointers don't match -- even though of the same"
| > 			" type and 'to the same object'!\n";
| > 
| > 	return 0;
| > };
|
|Huh? pa1 and pa2 does not point to the same object of type A. They point to
|different sub-objects the D each of type A. 
|
|I conjecture that people who think that pa1 and pa2 should point to the
|same object aren't confused about `object identity' but about the distinction
|between virtual and ordinary base classes (and the reason for that is often
|that they haven't read a good C++ textbook, but thought they could deduce
|the meaning of the example from first principles or experience with some
|other language).

I will counter-conjecture that people who consider this a trivial and
obvious example have not yet realized that pointers do not model object
identity in C++, in which case much of the arguments being held here
are moot.

Note that I said "'to the same object'" not "to the same object"

From one point of view only legal transformations from derived to base
classes have occured, so object identity must be maintained -- you're still
referring "'to the same object'" as you originally were referring to.
From the other point of view, clearly you end up with pointers to distinct
base objects, thus you cannot be referring "'to the same object'" 

In terms of object identity:

Does pb refer to the same object as &d?
Yes because B is a superclass of D

Does pc refer to the same object as &d?
Yes because C is a superclass of D

Does pa1 refer to the same object as pb?
Yes because A is a superclass of B

Does pa2 refer to the same object as pc?
Yes because A is a superclass of C

Does pa1 refer to the same object as pa2?
Yes because the chain of object identity has been maintained
No because in C++ the two base objects "are distinct"

Conclusions?

Pointers do not model object identity in C++.  Template classes
that assume pointers model unique identity of objects will not
work in general.  If the programmer of a class is to correctly model
object identity, they need to do so by how they program their class.
Trying to make the language maintain a one-to-one correspondence 
between pointers and object identity is not possible.  Issues
of "type of pointer" "type of object" "type of derivation" "empty classes" 
"vbases" "vptrs" "MI" etc all become pertinent to when or when not, how and 
how not pointer comparisons should work in C++.  "General" rules are doomed to
failure, because in general there is not a one-to-one correspondence
between pointers and object identity in C++.

Xref: sparky comp.std.c++:1946 comp.std.c:3311