Am I missing something in private inheritance?

I

Ioannis Vranos

May someone explain why does this compile?


class HiddenSealBaseClass
{
public:
HiddenSealBaseClass() { }
};

class Sealed: virtual HiddenSealBaseClass
{};

class SomeClass: Sealed
{
// Whatever
};




int main()
{
SomeClass obj;
}


Since we have *private* virtual inheritance, the public constructor
HiddenSealBaseClass() should have become private after Sealed
derivation, and thus inaccessible to SomeClass.
 
V

Victor Bazarov

Ioannis Vranos said:
May someone explain why does this compile?


class HiddenSealBaseClass
{
public:
HiddenSealBaseClass() { }
};

class Sealed: virtual HiddenSealBaseClass
{};

class SomeClass: Sealed
{
// Whatever
};




int main()
{
SomeClass obj;
}


Since we have *private* virtual inheritance, the public constructor
HiddenSealBaseClass() should have become private after Sealed derivation,
and thus inaccessible to SomeClass.

That's utter nonsense.

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

class B : A { // private inheritance
};

int main() {
A a;
a.foo(); // according to you it shouldn't compile because
// somebody else inherits from A privately
}

Victor
 
A

Alf P. Steinbach

* Victor Bazarov:
That's utter nonsense.

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

class B : A { // private inheritance
};

int main() {
A a;
a.foo(); // according to you it shouldn't compile because
// somebody else inherits from A privately
}

The problem is more subtle than that, Victor, in your example
somewhat analogous to

class C: public B
{
void victorLookHere(){ foo(); }
};

What might make the analogy break down is that this is about a
default constructor and virtual inheritance, not ordinary
inheritance and an ordinary member function or constructor.

The reason there is doubt is that at least three modern compilers
don't complain.
 
I

Ioannis Vranos

Victor said:
That's utter nonsense.

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

class B : A { // private inheritance
};

int main() {
A a;
a.foo(); // according to you it shouldn't compile because
// somebody else inherits from A privately
}




Nope. You are using two classes while I am using three. Making your
example more equivalent:



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

class B : A {
};


class C: B {};

int main() {
C a;
a.foo();
}


This does not compile.



or even more equivalent:

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

class B : virtual A {
};


class C: B {};

int main() {
C a;
a.foo();
}



The above does not compile too, however it does compile if we use a
public A() constructor.
 
V

Victor Bazarov

Alf said:
* Victor Bazarov:



The problem is more subtle than that, Victor, in your example
somewhat analogous to

class C: public B
{
void victorLookHere(){ foo(); }

So, we're saying that in this case 'C' shouldn't know that it's derived
from 'A' (as well) since 'A' is a private base of 'B', right? IOW, to
anybody outside 'B' B::foo() does not exist, right? Actually I agree.

So, in 'C' scope, 'foo' shouldn't be resolved to A::foo because 'C' must
not know about 'A' being one of its base classes. Perfectly fine.
};

What might make the analogy break down is that this is about a
default constructor and virtual inheritance, not ordinary
inheritance and an ordinary member function or constructor.

Yes. The need to construct a virtual base class object in the most
derived class' constructor makes the whole thing tricky.
The reason there is doubt is that at least three modern compilers
don't complain.

So, Alf, what's your take on it? I say, since the default c-tor of the
virtual base class is public, it should be accessible. Do you think
otherwise? Could you give justification (from the Standard) why it would
not be accessible? While you're at it, look at 12.6.2/6. "If V does not
have an accessible default constructor, the initialisation is ill-formed".
IOW, if it does [have an accessible default constructor], it would be OK.

Thanks.

V
 
V

Victor Bazarov

Ioannis said:
Nope. You are using two classes while I am using three. Making your
example more equivalent:



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

class B : A {
};


class C: B {};

int main() {
C a;
a.foo();
}


This does not compile.

Of course it doesn't. You're treating 'foo' as if it's a member of 'C'.
Your original post required access to A::A(), which was never private to
begin with.
or even more equivalent:

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

class B : virtual A {
};


class C: B {};

int main() {
C a;
a.foo();
}



The above does not compile too, however it does compile if we use a
public A() constructor.

Again. C::foo is private. A::A is not.

Victor
 
A

Alf P. Steinbach

* Victor Bazarov:
So, Alf, what's your take on it? I say, since the default c-tor of the
virtual base class is public, it should be accessible. Do you think
otherwise?

In part I do. I disagree strongly with the justification, it does not make
sense to me. Regarding the conclusion, for the specific case of default
constructor, I do not know.

Could you give justification (from the Standard) why it would
not be accessible?

Private inheritance.

It gives non-accessibility for anything except the generated default
constructor.

For the generated default constructor, I do not know, but as earlier
stated I strongly suspect a compiler bug in three compilers, namely Comeau, GNU
and MSVC.

For example, the following code does _not_ compile with MSVC, which is as it
should be IMHO:


class HiddenSealBaseClass
{
public:
HiddenSealBaseClass() { }
};

class Sealed: virtual HiddenSealBaseClass
{};

class SomeClass: Sealed
{
SomeClass(): HiddenSealBaseClass() {}
// Whatever
};

int main()
{
SomeClass obj;
}


vc_project.cpp(22): error C2248: 'SomeClass::SomeClass' : cannot access private
member declared in class 'SomeClass'
 
V

Victor Bazarov

Alf P. Steinbach said:
* Victor Bazarov:

In part I do. I disagree strongly with the justification, it does not
make
sense to me. Regarding the conclusion, for the specific case of default
constructor, I do not know.



Private inheritance.

It gives non-accessibility for anything except the generated default
constructor.

For the generated default constructor, I do not know, but as earlier
stated I strongly suspect a compiler bug in three compilers, namely
Comeau, GNU
and MSVC.

For example, the following code does _not_ compile with MSVC, which is as
it
should be IMHO:


class HiddenSealBaseClass
{
public:
HiddenSealBaseClass() { }
};

class Sealed: virtual HiddenSealBaseClass
{};

class SomeClass: Sealed
{
SomeClass(): HiddenSealBaseClass() {}
// Whatever
};

int main()
{
SomeClass obj;
}


vc_project.cpp(22): error C2248: 'SomeClass::SomeClass' : cannot access
private
member declared in class 'SomeClass'

This is where I am puzzled to the extreme. It seems that SomeClass has
less access to 'HiddenSealBaseClass' than anybody else. That goes against
_any_ possible role an access specifier is supposed to play.

Now, here is another example where it would be really bad.

I have two classes, B and D. B has a public default constructor (whether
it's generated or user-defined shouldn't matter). In D I have an object
of type B, which is created using all default ways (no mention of it in
the D's constructor initialiser list). Now, I decide to inherit [some
functionality] from a third-party class C, which at the time virtually and
publicly derived from B. My program is well-formed. Now, the third party
decides to change public inheritance to private. BAM! Suddenly, my
program's well-formedness depends on whether C is derived from B and how.
What?!! No, sorry, B's constructor is public and it should be accessible
_no_matter_ who and how intends to use it.

The main point of private inheritance is to prevent automatic conversions
from the derived to base. When the base class is used/instantiated without
any intervening derived members (and that's the case in virtual inheritance
among others), IOW, directly, the access used is the one that's specified
by the base class _itself_.

Victor
 
I

Ioannis Vranos

Victor said:
Again. C::foo is private. A::A is not.


Yes, however, why this does not happen in the case of a public default
constructor?

It looks like the type of inheritance (private, protected, public), does
not affect inherited public/protected constructors, but only inherited
public/protected data members and member functions.

Is this right?
 
V

Victor Bazarov

Ioannis Vranos said:
[..]
It looks like the type of inheritance (private, protected, public), does
not affect inherited public/protected constructors, but only inherited
public/protected data members and member functions.

Is this right?

Constructors are not inherited, perhaps that's the explanation you're
looking for.

Victor
 
I

Ioannis Vranos

Victor said:
Constructors are not inherited, perhaps that's the explanation you're
looking for.


Yes, that's it I guess.


However (*this is another case*) strangely enough, this code from the
FAQ works:


class Fred;

class FredBase {
private:
friend class Fred;
FredBase() { }
};

class Fred : private virtual FredBase {
public:
...
};



That is, although FredBase() constructor is *private*, Fred being a
friend of FredBase "has access" to this constructor.


So in summary, constructors are not inherited, however a class being a
friend can access private constructors as happens with usual private
methods.
 

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
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top