views:

601

answers:

5

I’m trying to do the following:

class Animal
{
    class Bear : public Animal
    {
        // …
    };

    class Giraffe : public Animal
    {
        // …
    };
};

… but my compiler appears to choke on this. Is this legal C++, and if not, is there a better way to accomplish the same thing? Essentially, I want to create a cleaner class naming scheme. (I don’t want to derive Animal and the inner classes from a common base class)

+3  A: 

Doesn't really answer the question, but I think you're misusing nested class, maybe you should have a look at namespaces (by the way, the answer is "it's not possible, because Animal is an incomplete type").

Luc Touraille
+11  A: 

The class type is considered incomplete until the end of its definition is reached. You cannot inherit from incomplete class so you cannot inherit from enclosing class.

EDIT: Correction
As Richard Wolf corrected me: It is possible to inherit from enclosing class if you delay the definition of the nested classes. See his answer for details.

Tadeusz Kopec
It is possible by forward declaring the contained class.
Richard Wolf
I didn't know it's allowed to define nested class outside the enclosing class. But tried and, surprisingly for me, it works.
Tadeusz Kopec
@tkopec, why don't you edit your answer to correct your statement? It would give you your two points back, and me my one. I find it weird, especially since you *know* it is wrong, now.
Johannes Schaub - litb
Done correcting. But now the comments stop making sense.
Tadeusz Kopec
@tkopec, i believe people can still read it sensefully. Since you answered to those comments, they will see you edited the answer. They can also look up the answer's history log and consult earlier versions. I believe that's still better than keeping a wrong answer just to keep making comments directly refer to the current text. Thanks for making it clearer.
Johannes Schaub - litb
+1  A: 

I'm not clear what you are trying to achieve here but you may be able to get it via namespaces.

namespace creatures
{

class Animal
{
};

class Bear : public Animal
{
};

class Giraffe : public Animal
{
};


}

This declares Bear and Giraffe as types of animals but puts the whole thing in a namespace if you are looking for the base class to not pollute the global namespace.

Corwin Joy
+15  A: 

You can do what you want, but you have to delay the definition of the nested classes.

class Animal
{
   class Bear;

   class Giraffe;
};

class Animal::Bear : public Animal
{
};


class Animal::Giraffe : public Animal
{
};
Richard Wolf
A: 

It's always worth considering the ATL method of "Upside-Down Inheritance". It makes my head hurt every time I need to do this, but the efficiency of the object-code you get is unbeatable. Somewhere I clipped the article by Jim Beveridge which was the best explanation I ever saw, but this is hard to find today, I just see a reference to it.

"Mar 25, 2004 ... An excellent article from Jim Beveridge: ATL and Upside-Down Inheritance.."

pngaz