nested class inheriting from outer class

R

Richard Lee

For some reason, this does not compile.

class A
{
public:
class B : public A
{
public:
B() : A() {}
};

protected:
A() {}
};

I can't figure out what is wrong with this construct. It works fine in
other languages (e.g. Java). It's quite useful to be able to declare a
class, and then subclass it a bunch of different ways while scoping the
subclasses to a namespace based on the name of their superclass. I
can't see any semantic problems, since you can declare nested classes in
C++, and you can inherit from classes in C++, but you can't do both?

Maybe it's just a bug in my compiler? I'm using gcc version 4.1.3. Or
is it a flaw in the C++ language specification?

Richard
 
Y

yanlinlin

For some reason, this does not compile.

class A
{
public:
     class B : public A
     {
     public:
         B() : A() {}
     };

protected:
     A() {}

};

I can't figure out what is wrong with this construct.   It works fine in
other languages (e.g. Java).  It's quite useful to be able to declare a
class, and then subclass it a bunch of different ways while scoping the
subclasses to a namespace based on the name of their superclass.  I
can't see any semantic problems, since you can declare nested classes in
C++, and you can inherit from classes in C++, but you can't do both?

Maybe it's just a bug in my compiler?  I'm using gcc version 4.1.3.  Or
is it a flaw in the C++ language specification?

Richard

At the position of class B (within class A), the declaration of class
A has not been finished. Since the compiler can not deside the size of
class A, you can not derive from it.
 
J

James Kanze

For some reason, this does not compile.
class A
{
public:
class B : public A
{
public:
B() : A() {}
};
protected:
A() {}
};
I can't figure out what is wrong with this construct.

It's illegal.
It works fine in other languages (e.g. Java).

Java has to make it work, since it requires all of the
implementation of A to be encapsulated in A.
It's quite useful to be able to declare a class, and then
subclass it a bunch of different ways while scoping the
subclasses to a namespace based on the name of their
superclass.

Why do you want to scope them to the namespace of the
superclass? If they're just implementation details, depending
on your file organization, it might be appropriate to just
define them in the anonymous namespace of the implementation
file. Otherwise, there's nothing forbidding you from creating a
namespace A_private, or whatever, for them. Finally, you can do
something like:

class A
{
public:
class B ;
// ...
} ;

class A::B
{
public:
B() ;
} ;
I can't see any semantic problems, since you can declare
nested classes in C++, and you can inherit from classes in
C++, but you can't do both?

When you inherit, the class you're inheriting from must be
complete.
Maybe it's just a bug in my compiler? I'm using gcc version
4.1.3. Or is it a flaw in the C++ language specification?

Neither. It works as designed.
 
M

Michael.Boehnisch

For some reason, this does not compile.

class A
{
public:
class B : public A
{
public:
B() : A() {}
};

protected:
A() {}

};

It does not compile for good reason. Let's assume the construct were
allowed. B inherits from A which means everything defined in A is also
available inside B. This includes B... so B will offer a class B::B
that is also derived from A. By recursion you'll get B::B::B,
B::B::B::B, .... ad infinitum.
The compiler would have to generate an infinite number of types.

I do not know enough about Java, but I assume it only works if
embedded classes do not become an integral part of the surrounding
class.

best,

Michael
 
J

James Kanze

It does not compile for good reason. Let's assume the
construct were allowed. B inherits from A which means
everything defined in A is also available inside B. This
includes B... so B will offer a class B::B that is also
derived from A. By recursion you'll get B::B::B, B::B::B::B,
.... ad infinitum.
The compiler would have to generate an infinite number of types.

Not really. All that it would mean is that the type A::B is
present in A::B. Which it is anyway because of class name
injection.

Obviously, in this case, A could not have a data member of type
B.
I do not know enough about Java, but I assume it only works if
embedded classes do not become an integral part of the
surrounding class.

In Java, variables (data members of classes) can never be
objects. A variable in Java corresponds to a pointer in C++.
(There are exceptions for certain fundamental types, like int,
but they don't concern us here.)
 

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,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top