2010-04-08 3 views
32

Можно ли переслать-объявить вложенный класс, а затем использовать его как тип для конкретного (не указателя на/ссылку) элемента данных внешнего класса?Проблема с вложенным объявлением класса/прямой C++

I.E.

class Outer; 

class Outer::MaybeThisWay // Error: Outer is undefined 
{ 
}; 

class Outer 
{ 
MaybeThisWay x; 

class MaybeThatOtherWay; 

MaybeThatOtherWay y; // Error: MaybeThatOtherWay is undefined 
}; 
+0

Ваш код выглядит бесконечной цепи "Outer содержит наружный содержит наружный содержит Outer ..." – Muxecoid

+0

Возможный дубликат [Как переадресовать объявить внутренний класс?] (Http://stackoverflow.com/questions/1021793/how-do-i-forward-declare-an-inner-class) –

ответ

37

Вы не можете переслать-объявить вложенный класс.

В зависимости от того, что вы пытаетесь сделать, возможно, вы можете использовать пространство имен, а не класс на внешнем слое. Вы можете переадресовать-объявить такой класс не проблема:

namespace Outer { 
    struct Inner; 
}; 

Outer::Inner* sweets; // Outer::Inner is incomplete so 
         // I can only make a pointer to it 

Если ваш внешний абсолютно должен быть классом, и вы не можете обуви рожок его в пространство имен, то вам нужно для Outer быть полный тип в контексте, в котором вы отправляете объявление Inner.

class Outer 
{ 
    class Inner; // Inner forward-declared 
}; // Outer is fully-defined now 

Outer yes; // Outer is complete, you can make instances of it 
Outer::Inner* fun; // Inner is incomplete, you can only make 
        // pointers/references to it 

class Outer::Inner 
{ 
}; // now Inner is fully-defined too 

Outer::Inner win; // Now I can make instances of Inner too 
1

Нет, но то, что случилось с

class Outer { 
public: //or protected or private 
    class Inner { 
    }; 

private: 
    Inner foo; 
}; 

вперед объявляя не имеет смысла здесь, если я что-то (что возможно увидеть, как ваш вопрос отсутствует отсутствует в большом количестве деталей)

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

+1

Поскольку Inner не является прямым заявил, что он полностью определен там. – CashCow

+0

Что делать, если вы должны были отменить разделы здесь. Возможно, некоторые функции в публичном разделе используют частные переменные, поэтому они должны быть объявлены, но Inner тоже должен быть закрыт. Как разрешить Inner видеть в частном разделе сейчас? – Sohaib

1

Если класс был объявлен вперед (но пока у вас еще нет полного определения), вы можете объявить ему только указатель, потому что компилятор еще не знает размер класса (или имена его полей или методов).

0

Если вы объявляете атрибут типа MaybeThatOtherWay, а не ссылку или указатель, компилятор должен знать полное определение класса для определения размера внешнего класса. Таким образом, вы не можете использовать форвардное объявление и такое объявление поля, будь то вложенный класс или нет.

15

Невозможно переслать объявление вложенного класса без полного указания содержащего класса. Этот маленький трюк вроде исправляет проблему, хотя

class Outer_Inner 
{ 
}; 

class Outer 
{ 
public: 
    typedef Outer_Inner Inner; 
}; 

Это работает для меня, как и в моем именовании Outer_Inner не является допустимым именем класса, так что очевидно, что это относится к вложенному классу.

Вы можете все еще не вперед объявить вложенный класс, как это:

class Outer::Inner; 

Но по крайней мере он может быть объявлен вперед с:

class Outer_Inner; 

Если вам не нравится, как Outer_Inner похоже, вы можете принять соглашение об именах для вложенных классов, которые лучше подходят вашим вкусам. Outer__Inner, Outer_nested_Inner и т. Д.

+3

Не используйте двойные подчеркивания - имена, содержащие два символа подчеркивания, зарезервированы для реализации для любого использования. См. Http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797 – villintehaspam

+0

Является ли та же проблема, с которой я столкнулся здесь? http://stackoverflow.com/questions/20214740/nested-class-as-a-template-parameter-of-parent-class-in-c –

0

Если вам просто нужен тип как параметр функции или статическая переменная, это можно сделать на стороне клиента.Например, чтобы получить уведомление о событии от Наружно:

Интерфейс:

class Client { 
public: 
private: 
    static void gotIt(int event); 
    class Helper; 
}; 

Реализация:

#include <outer.hpp> 

class Client::Helper { 
public: 
    static void fromOuter(Outer::Inner const& inner) 
    { 
     gotIt(inner.event()); 
    } 
}; 
Смежные вопросы