27

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)

David Nehme
  • 21,379
  • 8
  • 78
  • 117
Tony the Pony
  • 40,327
  • 71
  • 187
  • 281
  • 2
    For a start, you need to follow the closing braces with semicolons after a class declaration. – Dominic Rodger Sep 28 '09 at 08:42
  • I'm unclear on why you would want to do this. If I understand correctly, the Bear class will have a Bear class inside of it, which... seems a bit odd. – Brian Postow Dec 04 '09 at 15:31

5 Answers5

52

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
  • 4,039
  • 1
  • 21
  • 14
15

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 for Ukraine
  • 12,283
  • 6
  • 56
  • 83
  • 1
    It is possible by forward declaring the contained class. – Richard Wolf Sep 28 '09 at 13:00
  • 1
    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 for Ukraine Sep 28 '09 at 13:19
  • @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 Dec 03 '09 at 22:35
  • @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 Dec 04 '09 at 20:30
2

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
  • 79,925
  • 15
  • 92
  • 137
2

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.

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
Corwin Joy
  • 645
  • 7
  • 14
1

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
  • 377
  • 2
  • 10
  • The article has gone to electric heaven, but courtesy of archive.org, can be accessed at http://web.archive.org/web/20070805214320/http://apostate.com/programming/atlupsidedown.html. – ndkrempel Jul 15 '12 at 05:08