Private bases

D

Dave

Hello all,

Suppose that derived inherits privately from base. A base pointer may not
be made to point at a derived object in this case. I understand that is
exactly what is supposed to happen and I understand that this is explicitly
dictated by the Standard.

I'm trying to understand the diagnostic my compiler generates in this case
though:

'type cast' : conversion from 'derived *' to 'base *' exists, but is
inaccessible

Exactly WHAT is it that is inaccessible? A constructor? A destructor?
Consider this case:

class base {};
class derived: private base {};

There's nothing in either class to be inaccessible!!! Yet this diagnostic
results. Again, I do understand that this *IS* proper behavior. I'm just
trying to understand what underlying language mechanism is coming into play
here to enforce this restriction which is, indeed, explicitly requried by
the standard.

Also, just want to let everyone know I'm not trying to solve a particular
real-life problem here. This question is purely academic in nature, so
there is no answer to the oft-asked question "What are you trying to do?".
Just trying to learn, man!!!

Thanks!
Dave
 
T

Thomas Wintschel

....
Suppose that derived inherits privately from base. A base pointer may not
be made to point at a derived object in this case. I understand that is
exactly what is supposed to happen and I understand that this is explicitly
dictated by the Standard.

I'm trying to understand the diagnostic my compiler generates in this case
though:

'type cast' : conversion from 'derived *' to 'base *' exists, but is
inaccessible

Exactly WHAT is it that is inaccessible? A constructor? A destructor?
Consider this case:
....

I would guess that, in this diagnostic message, inaccessible == private
 
G

Gianni Mariani

Dave said:
Hello all,

Suppose that derived inherits privately from base. A base pointer may not
be made to point at a derived object in this case. I understand that is
exactly what is supposed to happen and I understand that this is explicitly
dictated by the Standard.

I'm trying to understand the diagnostic my compiler generates in this case
though:

'type cast' : conversion from 'derived *' to 'base *' exists, but is
inaccessible

Exactly WHAT is it that is inaccessible? A constructor? A destructor?
Consider this case:

class base {};
class derived: private base {};

This means that the only scope that has visibility into base is within
the class "derived".

theoretically you could write :

class derived: private base
{
base * get_base() { return this };
};

A method in derived is able to convert it's pointer to a base.
There's nothing in either class to be inaccessible!!!

"private" inheritance means that only the deriving class has access to
the base class.

Yet this diagnostic
results. Again, I do understand that this *IS* proper behavior.

That *IS* the proper behaviour because it is defined like this.

I'm just
trying to understand what underlying language mechanism is coming into play
here to enforce this restriction which is, indeed, explicitly requried by
the standard.

The reason "public", "protected" and "private" inheritance is to control
how classes can be used (i.e. what is supposed to be part of the
interface and what is part of the implementation).

Suppose you had to create a class that made "widgets". Now, suppose we
only wanted a very small interface (because your programmers just love
to mess with everything just because it's there and make a mess of
things) ... and suppose making "widgets" is very similar to making
"foobars" and so you can inherit from foobars but you only want a small
amount of the foobars interface exposed.

So - after all this supposing - here is an example:

class make_foobars
{
public:

void check_maker();

void make_stuff();

void foobar_stuff();
};


class make_widgets : private make_foobars
{
public:

using make_foobars::check_maker; // we really want check_maker

void make_stuff();
};

int main()
{
make_widgets widget_maker;

widget_maker.check_maker(); // calls foobar::check_maker()

widget_maker.make_stuff(); // calls make_widgets::make_stuff()

// widget_maker.foobar_stuff(); // Can't do this ... this is foobar.

};

There is another way to do this use pure abstract classes. Notw that
this mechanism is very good for reducing the coupling between
application, interface and implementation even in compiled versions of
the implementation.


// Header file (interface) ..........
class make_widgets
{
public:

virtual ~make_widgets() {};

virtual void make_stuff() = 0;

virtual void check_maker() = 0;

protected :
make_widgets() {};

};

make_widgets * new_widget_maker();
// End header file ...........


// Implementation (.cpp file) ...........
class make_widgets_impl : public make_foobars, public make_widgets
{

void make_stuff();

void check_maker()
{
make_foobars::check_maker();
}

};

make_widgets * new_widget_maker()
{
return new make_widgets_impl;
}

// End of .cpp file

// using widget maker (application).
int main()
{
make_widgets * y = new_widget_maker();

y->make_stuff();

y->check_maker();

delete y;
}

..................

In the example above - the implementation of make_widgets is completly
hidden. There are NO dependantcies other than the ones in the interface
between the implementation and the application.

This is used by COM and various "plug-in" systems however it is also
just good practice to define clearly what the "interface" is.
 
D

Domenico Andreoli

Gianni said:
class make_foobars
{
public:

void check_maker();

void make_stuff();

void foobar_stuff();
};


class make_widgets : private make_foobars
{
public:

using make_foobars::check_maker; // we really want check_maker

void make_stuff();
};

again i see a lot of similarities between classes/structs and
namespaces.. they must be strict cousins in the inner compiler
representation...

-----[ Domenico Andreoli, aka cavok
--[ http://filibusta.crema.unimi.it/~cavok/gpgkey.asc
---[ 3A0F 2F80 F79C 678A 8936 4FEE 0677 9033 A20E BC50
 
R

Ron Natalie

Dave said:
Exactly WHAT is it that is inaccessible? A constructor? A destructor?

The whole class. The class is termed accessible if an arbitrary invented
member would be accessible.

Here base::foo() (if there were such a foo()) would not be accessible in derived,
so the class "base" is not accessible.
 
C

Chris Theis

Domenico Andreoli said:
again i see a lot of similarities between classes/structs and
namespaces.. they must be strict cousins in the inner compiler
representation...

Which seems reasonable, doesn't it? :)

Chris
 
D

Dave

Ron Natalie said:
The whole class. The class is termed accessible if an arbitrary invented
member would be accessible.

Here base::foo() (if there were such a foo()) would not be accessible in derived,
so the class "base" is not accessible.

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

class derived: private base
{
};

base::foo() *is* accessible inside of derived! The only case where it would
not be is if it were private, but a private base member is never accessible
in the derived class in *any* case!
 
T

tom_usenet

Hello all,

Suppose that derived inherits privately from base. A base pointer may not
be made to point at a derived object in this case. I understand that is
exactly what is supposed to happen and I understand that this is explicitly
dictated by the Standard.

I'm trying to understand the diagnostic my compiler generates in this case
though:

'type cast' : conversion from 'derived *' to 'base *' exists, but is
inaccessible

Exactly WHAT is it that is inaccessible? A constructor? A destructor?

The conversion from derived* to base*, just as it says. That
conversion is only accessible inside derived or using a c-style cast.
I don't understand the question, given that you present the answer
within the question...
Consider this case:

class base {};
class derived: private base {};

There's nothing in either class to be inaccessible!!! Yet this diagnostic
results. Again, I do understand that this *IS* proper behavior. I'm just
trying to understand what underlying language mechanism is coming into play
here to enforce this restriction which is, indeed, explicitly requried by
the standard.

It's just that there is an implicit conversion from derived* to base*
that is accessible globally if the inheritence is public, but only
within derived if it is private.

Tom
 
M

Mike Wahler

again i see a lot of similarities between classes/structs and
namespaces.. they must be strict cousins in the inner compiler
representation...

Not necessarily, but they are indeed related, in that they
all define a scope. A struct and a class are the same thing
except that they have different default access.

-Mike
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top