Q: Inheritance design issue

J

Jakob Bieling

Hi,

Suppose I have a base class and a derived class as follows:

class base
{
public:
void somefunc ();
};

class derived : private base
{
public:
void someotherfunc ();
};

My intend is to prevent the user of 'derived' to access the members of
'base'. The problem is that nothing prevents the user to down-cast the
'derived' class to the 'base' class and then access that member. Is there a
solution to this, other than simply documenting it?

thanks!
 
R

Rolf Magnus

Jakob said:
Hi,

Suppose I have a base class and a derived class as follows:

class base
{
public:
void somefunc ();
};

class derived : private base
{
public:
void someotherfunc ();
};

My intend is to prevent the user of 'derived' to access the
members of 'base'.

Why? The whole idea of inheritance is that a 'derived' can be used like
a 'base' and shares its interface. If you need another interface,
consider making derived a member of base.
The problem is that nothing prevents the user to down-cast the
'derived' class to the 'base' class and then access that member. Is
there a solution to this, other than simply documenting it?

Again, make derived a member of base.
 
R

Ron Natalie

Jakob Bieling said:
My intend is to prevent the user of 'derived' to access the members of
'base'. The problem is that nothing prevents the user to down-cast the
'derived' class to the 'base' class and then access that member. Is there a
solution to this, other than simply documenting it?
The only way (safely) to down convert derived to base is to use a C-style cast. That's
the one cast the C-style cast will do that the C++ casts won't. In order to cast via a
C++ cast (or even implicitly convert) the base class would need to be accessible (i.e.,
not private). A reinterpret_cast is dangerous (there's no guarantee that the converted
pointer would be correct, and in the case of multiple inheritance it almost assuredly is
wrong for some of the bases).
 
R

Rolf Magnus

Rolf said:
Why? The whole idea of inheritance is that a 'derived' can be used
like a 'base' and shares its interface. If you need another interface,
consider making derived a member of base.


Again, make derived a member of base.

Grmbl. I just got used to not reading my postings anymore before sending
them, which is not a good idea. Of course I mean making base a member
of derived.
 
J

jeffc

Jakob Bieling said:
class base
{
public:
void somefunc ();
};

class derived : private base
{
public:
void someotherfunc ();
};

My intend is to prevent the user of 'derived' to access the members of
'base'. The problem is that nothing prevents the user to down-cast the
'derived' class to the 'base' class and then access that member.

Users can't get access to private members simply by casting. What results
are you seeing that makes you think they can?
 
J

Jakob Bieling

The only way (safely) to down convert derived to base is to use a C-style cast. That's
the one cast the C-style cast will do that the C++ casts won't. In order to cast via a
C++ cast (or even implicitly convert) the base class would need to be accessible (i.e.,
not private). A reinterpret_cast is dangerous (there's no guarantee that the converted
pointer would be correct, and in the case of multiple inheritance it almost assuredly is
wrong for some of the bases).

Does this mean due to the 'private' inheritance, my compiler should flag
an error, unless I use a C-style cast?
 
J

jeffc

Rolf Magnus said:
Why? The whole idea of inheritance is that a 'derived' can be used like
a 'base' and shares its interface.

But the whole point of *private* inheritance is to hide the interface from
users of "derived".
 
J

Jakob Bieling

jeffc said:
Users can't get access to private members simply by casting. What results
are you seeing that makes you think they can?


I thought that by casting the 'derived' object to a 'base' object, you
can then access the 'somefunc' member, which you would otherwise not be able
to access. But Ron's post shed some light on this, though I am still not
100% that I understood him right.
 
J

Jakob Bieling

Hi,

I forgot to mention that I need to store both the 'base' objects and the
'derived' objects in one array (which is why I could not use Rolf's
suggestion). This also makes my question a pretty useless one, because when
storing the 'derived' pointers as 'base' pointers, I would do exactly what I
am trying to prevent. So now I came up with having a common base class to
both 'base' and 'derived' and do not let 'derived' derive from 'base' (now
the class names seem rather badly chosen).

It also prevents code duplication which I will get when finishing both
classes later. I should have thought a little more before posting, my
apologies.

Thanks for your time!
 
S

Shane Beasley

Jakob Bieling said:
class base
{
public:
void somefunc ();
};

class derived : private base
{
public:
void someotherfunc ();
};

My intend is to prevent the user of 'derived' to access the members of
'base'. The problem is that nothing prevents the user to down-cast the
'derived' class to the 'base' class and then access that member. Is there a
solution to this, other than simply documenting it?

Private inheritance prevents regular (non-friend) users from casting
between base and derived classes using static_cast or dynamic_cast. It
does *not* prevent them from using C-style cast notation to perform
such casts. However, any competent programmer should know not to use
C-style casts here (or just about anywhere, really).

Best practice: Use private inheritance and leave it at that. Do not
bother documenting how (not) to use C++ features that the user should
already know about, or that are beyond your control.

BTW: Casting from a subclass (derived class) to a superclass (base
class) is upcasting, not downcasting.

- Shane
 
J

Jakob Bieling

BTW: Casting from a subclass (derived class) to a superclass (base
class) is upcasting, not downcasting.


Oh, using the words sub- and superclass it makes perfect sense, yes!
Thanks for the clarification!
 

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

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,825
Members
47,371
Latest member
Brkaa

Latest Threads

Top