Topic: Constructing A from B


Author: ark@alice.att.com (Andrew Koenig)
Date: 20 Jul 93 16:28:22 GMT
Raw View
In article <CAGts0.372@world.std.com> smayo@world.std.com (Scott A Mayo) writes:

> The "solution" I hit on, and I don't like it, is
>     *(A*)this = *a;
> which does in fact assign all the values over for the in-common member
> variables. It works because, at least in Microsoft C7, the order of
> member variables in a derived class instance puts the base class first.

No, it works because C++ defines conversion of a derived class pointer
to a base class pointer as an operation that yields a pointer that points
to the base class part of the derived class object.

The technique above is well-defined and portable.

A slightly shorter way to write it might be

 ((A&) *this) = *a;

where the outer parentheses are actually unnecessary.
--
    --Andrew Koenig
      ark@research.att.com




Author: smayo@world.std.com (Scott A Mayo)
Date: Tue, 20 Jul 1993 13:35:57 GMT
Raw View
I have what may be a dumb C++ question. I'm familiar with C, and
generally with OOP; but I am having trouble getting a specific
behaviour from C++.

I have a class, A, and a derived class, B. I have several thousand
instances of A in memory (on a PC... sigh) and exactly one instance
of B. The difficulty is that at any given moment, an instance of
class A can be chosen to *become* that instance of B - A's are effectively
promoted and demoted at runtime. B contains a goodly number of pieces of data
that A does not, and for that reason alone I can't afford to just make
everything an instance of class B. (Besides, that would be conceptually
wrong.)

The problem arises in the code associated with
    B b(a);
specifically the constructor for B that creates a B from one of my a's.
At the end of the construction, b should have all the values a had,
plus the extra ones required by B. But C++ is certainly not going to
allow
    *this /*which is B*/   = a; // assign the common values over...
inside the constructor. Obviously I can do
    m1 = a.m1, m2 = a.m2, ...; // for all member variables of A
for each of the members defined in A and inherited by B, but this is
volatile code and the member list of A changes daily, so that code has
to change daily as well, which is awkward, especially when I forget to
update it.

The "solution" I hit on, and I don't like it, is
    *(A*)this = *a;
which does in fact assign all the values over for the in-common member
variables. It works because, at least in Microsoft C7, the order of
member variables in a derived class instance puts the base class first.
But it is sort of grotesque; good thing I only have one base class here.
My questions:

Does C++ make any guarantees about the ordering of member variables,
so that code like *(A*)this = *a; would work reliably? Is there some
better way to fill an instance of a derived class with the values of
a base class instance? It seems as if there should be. In C, types A and B
would be structs and B would contain an instance of A, so I'd be all
set with b.a = a;. Even COBOL would give me MOVE CORRESPONDING or
something.  What am I missing??

If no neat mechanism exists, can someone propose one? Promoting an object
up or down in an "is a" relationship at runtime can't be all that
unusual a thing to want to do...