C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Private interface using reinterpret_cast vs. inheritance

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
news_mail_jpa@hotmail.com
Guest





PostPosted: Sun Aug 28, 2005 1:31 pm    Post subject: Private interface using reinterpret_cast vs. inheritance Reply with quote



Try this here too (a bit modified)... looks like no success in
comp.lang.c++ ;)

----

Hi!

I'd like to implement a private interface and I have the choices
mentioned in the subject. The implementation using private inheritance
is probably cleaner but it also adds some space and time overhead
compared to the 'cast' -method. The problem with the cast method is
that I don't know whether its C++ standard-compliant and/or portable?

Example:

// Inheritance method
class LayerData {
public:
virtual int usefullStuffToLayer() = 0;
virtual Object* getObjectInterface() = 0;

};

class Layer {
public:
void doSomething(LayerData* p)
{
int stuff = p->usefullStuffToLayer();
// needs the Object -interface e.g. in callbacks
xyz->result(p->getObjectInterface());
};

};

class Object : private LayerData {
public:
void clientMethod() { pNext_->doSomething(this); };

private:
virtual int usefullStuffToLayer() { return 1; };
virtual Object* getObjectInterface() { return this; };

Layer* pNext_;

};

Object offers an interface to its clients but wants to hide the
LayerData part. That private interface is passed along when forwarding
calls to the Layer. However, for some reason the Layer also needs the
Object -interface, hence the conversion method. This is okay but it
adds some space (vtbl) and time overhead (v-methods) so I started to
think something like:

class LayerData {
public:
int usefullStuffToLayer() { return 1; };
Object* getObjectInterface()
{ return reinterpret_cast<Object*>(this) };
private:

LayerData() {};

friend class Object;

// all Object data items here
Layer* pNext_;

};

// Layer stays the same

class Object {
public:
void clientMethod() { data_.pNext_->doSomething(&data_); };

private:
// this will be the only data-item
LayerData data_;

};

So, is this portable and/or standard-compliant? Of course I could add a
parent-pointer to the LayerData-object but I wouldn't like to unless
forced to do so (that would effectively reserve the space spared from
the not_needed vtbl-pointer). Object doesn't inherit anything and
nobody is going to inherit from it. Am I going to hit some memory
alignment issues or something similar?

BR, jpa


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gerhard Menzl
Guest





PostPosted: Mon Aug 29, 2005 4:36 pm    Post subject: Re: Private interface using reinterpret_cast vs. inheritance Reply with quote



[email]news_mail_jpa (AT) hotmail (DOT) com[/email] wrote:

Quote:
class LayerData {
public:
virtual int usefullStuffToLayer() = 0;
virtual Object* getObjectInterface() = 0;

};

class Layer {
public:
void doSomething(LayerData* p)
{
int stuff = p->usefullStuffToLayer();
// needs the Object -interface e.g. in callbacks
xyz->result(p->getObjectInterface());
};

};

class Object : private LayerData {
public:
void clientMethod() { pNext_->doSomething(this); };

private:
virtual int usefullStuffToLayer() { return 1; };
virtual Object* getObjectInterface() { return this; };

Layer* pNext_;

};

Object offers an interface to its clients but wants to hide the
LayerData part. That private interface is passed along when forwarding
calls to the Layer. However, for some reason the Layer also needs the
Object -interface, hence the conversion method.

If I understand you correctly, Layer needs access to LayerData, but you
don't want other clients of Object to fiddle around with LayerData,
hence you make it a private interface to keep it exclusive. Fine. Now
Layer also needs to access Object via its public interface. Why don't
you just pass a pointer or reference to Object as a second argument?

class Layer {
public:
void doSomething(LayerData* p, Object* o)
{
int stuff = p->usefullStuffToLayer();
// needs the Object -interface e.g. in callbacks
xyz->result(o);
};
};

Why burden Layer with all that conversion and identity business? Layer
needs an interface through which it acquires its "usefull stuff", and it
needs an interface for its callbacks. That both are implemented by the
same concrete class is an implementation detail of Object and not
something that Layer should care about, at least not in a well-designed,
properly decoupled system.

Quote:
This is okay but it adds some space (vtbl) and time overhead
(v-methods)

How much space and time, and compared to what? Have you measured the
difference? Does it matter?

Quote:
so I started to think something like:

class LayerData {
public:
int usefullStuffToLayer() { return 1; };
Object* getObjectInterface()
{ return reinterpret_cast<Object*>(this) };
private:

LayerData() {};

friend class Object;

// all Object data items here
Layer* pNext_;

};

// Layer stays the same

class Object {
public:
void clientMethod() { data_.pNext_->doSomething(&data_); };

private:
// this will be the only data-item
LayerData data_;

};

So, is this portable and/or standard-compliant?

No, it's definitely not portable. The standard allows explicit
conversion via reinterpret_cast from a pointer to an object to a pointer
to an object of different type, but with a single exception, the results
of the conversion are unspecified, meaning it's up to the indivdual
compiler (5.2.10/7). You are basically lying to the compiler, telling it
that a pointer points to an Object when it really points to a class of a
different, unrelated type. Since layout compatibility between unrelated
classes or structs is only guaranteed for POD types, which your classes
are not, accessing a member through the forged pointer may easily result
in undefined behaviour. Your code does not even attempt to achieve
compatible layout (not that it would succeed if you did).

reinterpret_cast is a low-level sledgehammer of last resort. Don't use
it like this. If a function needs to access an Object, pass one.

--
Gerhard Menzl

#dogma int main ()

Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.