2009-09-28 6 views
17

Я пытаюсь сделать следующее:Может ли вложенный класс C++ наследовать свой охватывающий класс?

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

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

... но мой компилятор, кажется, задушить на этом. Является ли это законным C++, а если нет, есть ли лучший способ сделать то же самое? По сути, я хочу создать более чистую схему именования классов. (Я не хочу выводить Animal и внутренние классы из общего базового класса)

+2

Для начала, вы должны следовать за скобками закрытия с запятой после объявления класса. –

+0

Я не понимаю, почему вы хотели бы это сделать. Если я правильно пойму, класс Bear будет иметь внутри него класс Bear, который ... кажется немного странным. –

ответ

37

Вы можете делать то, что хотите, но вам нужно отложить определение вложенных классов.

class Animal 
{ 
    class Bear; 
    class Giraffe; 
}; 

class Animal::Bear : public Animal {}; 

class Animal::Giraffe : public Animal {}; 
2

Не отвечает на вопрос, но я думаю, что вы злоупотребляете вложенным классом, возможно, вам стоит взглянуть на пространства имен (Кстати, ответ «это невозможно, потому что Animal является неполным типом»).

15

Тип класса считается незавершенным до тех пор, пока не будет достигнут конец его определения. Вы не можете наследовать от неполного класса, чтобы вы не могли наследовать из окружающего класса.

EDIT: Коррекция
Как Richard Wolf поправил меня: можно наследовать от вмещающих класс, если вы задержать определение вложенных классов. См. Его ответ для деталей.

+1

Это можно путем переадресации объявленного класса. –

+1

Я не знал, что разрешено определять вложенный класс вне класса. Но попробовал и, что удивительно, для меня это работает. –

+0

@tkopec, почему бы вам не изменить свой ответ, чтобы исправить ваше заявление? Это даст вам ваши два очка, а я один. Я нахожу это странным, тем более, что вы уже знаете, что это неправильно. –

2

Я не понимаю, чего вы пытаетесь достичь здесь, но вы можете получить его через пространства имен.

namespace creatures 
{ 

class Animal 
{ 
}; 

class Bear : public Animal 
{ 
}; 

class Giraffe : public Animal 
{ 
}; 


} 

Объявляет Медведь и Жираф как виды животных, но ставит все это в пространстве имен, если вы ищете базовый класс, чтобы не загрязнять глобальное пространство имен.

0

Это всегда стоит рассматривать метод ATL «Наверху вниз наследования». У меня болит голова каждый раз, когда мне это нужно, но эффективность объектного кода, который вы получаете, непревзойденна. Где-то я обрезал статью Джима Бевериджа, которая была лучшим объяснением, которое я когда-либо видел, но этого трудно найти сегодня, я просто вижу ссылку на него.

«25 марта 2004 ... Отличная статья от Джима Бевериджа: ATL и Upside-Down Наследование ..»

+0

Статья отправилась на электрическое небо, но любезность archive.org, можно получить по адресу http://web.archive.org/web/20070805214320/http://apostate.com/programming/atlupsidedown.html. – ndkrempel

Смежные вопросы