A question about a section in "Inside the C++ Object Model"


G

goodbyeera

Following is quoted from "Inside the C++ Object Model" section 1.2:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`

If a programmer absolutely needs a data portion of an arbitrarily
complex C+
+ class to have the look and feel of an equivalent C declaration, that
porti
on is best factored out into an independent struct declaration. The
original
idiom for combining this C portion with its C++ part (see [KOENIG93])
was t
o derive the C++ part from the C struct:

struct C_point { ... };
class Point: public C_point { ... };

thus supporting both the C and c++ usage:

extern void draw_line(Point, Point);
extern "C" void draw_rect(C_point, C_point);

draw_line(Point(0, 0), Point(100, 100));
draw_rect(Point(0, 0), Point(100, 100));

This idiom is no longer recommended, however, because of changes to
the clas
s inheritance layout in some compilers (for example, the Microsoft C++
compi
ler) in support of the virtual function mechanism (see Section 3.4 for
a dis
cussion). Composition, rather than inheritance, is the only portable
method
of combining C and c++ portions of a class (the conversion operator
provides
a handy extraction method):

struct C_point { ... };

class Point {
public:
operator C_point() { return _c_point; }
// ...
private:
C_point _c_point;
// ...
};

One reasonable use of the C struct in C++, then, is when you want to
pass al
l or part of a complex class object to a C function. This struct
declaration
serves to encapsulate that data and guarantees a compatible C storage
layou
t. This guarantee, however, is maintained only under composition.
Under inheritance, the compiler decides whether additional data
members are inserted within the base struct subobject (again, see
Section 3.4 for a discussion, as well as Figures 3.2a and 3.2b).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I don't really understand why composition makes a difference from
inheritance in this case. Yes, if the derived class Point has a
virtual function then an object of class Point may have a vptr at the
beginning of the object, located before the data members of the base
struct C_point subobject (Microsoft VC++ does this way, and this is
the particular compiler and particular behavior that the author calls
out as the reason for his objection for inheritance in the text). But
that won't be so much of a problem. When the Point object is to be
converted to a C_point object when calling the "C" linkage function
draw_rect(), the default copy constructor of C_point will be invoked.
The parameter of the copy constructor is of type const C_point&.
Since C_point is a C-like structure without any virtual member
function (this assumption should be valid, since otherwise the
composition method will also fail to work anyway), that reference
parameter will not be a polymorphic-like reference, instead it's just
a simple reference directly to the C_point subobject (i.e. the
internal pointer representation of that reference will actually point
to the exact beginning of the C_point subobject, but not the vptr).
Thus, the copy constructor will just perform normally and the
resulting C_point object will be perfectly OK. And also if in some
other case a Point* is to be converted to a C_point*, proper pointer
arithmetic will also be performed (the pointer will be added with an
offset to skip over the vptr).
So my understanding is that, as long as the base C_point struct
contains no virtual member function, inheritance has the same effect
as composition, with regard to keeping C layout compatibility.
Can anyone point out what I am missing here? After all, I don't think
Mr. Lippman will ever make such a mistake left to be caught by a
newbie like me...
 
Ad

Advertisements

G

goodbyeera

My apology!
I am new to usenet, and I will try my best to be conforming to posting
guidelines in future.
Thank you for letting me know.

* (e-mail address removed):
[Multi-posting]

Don't.

Please read the group's FAQ and some general info on multiposting etc.

Cheers,

- Alf
 
F

Fraser Ross

Perhaps the example should involve a void* or a reinterpret_cast. There
are many other mistakes I've noticed in the code examples. The writing
isn't so bad.

Fraser.
 
Ad

Advertisements

F

Fraser Ross

The previous example in the book has a few mistakes with one
instruction. It should be:
strcpy(&pmumb1->pc[0], string);

Fraser.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top