Определение вложенного класса вне внешнего класса, в то время как внешний класс содержит экземпляр внутреннего класса

C++

Как я могу поместить определение внутреннего (вложенного) класса вне определения его внешнего (включающего) класса, где внешний класс имеет по крайней мере один экземпляр внутреннего класса в качестве члена данных? Я искал, но самый соответствующий ответ SO, который я нашел, - Определение вложенного класса в исходном файле, не имеет примера, где внешний класс имеет внутренний объект в качестве члена данных. Я следовал этому ответу, что касается объявления, но не определения внутреннего класса внутри определения внешнего класса, но мой код все еще не работает:

struct Outer
{
    struct Inner;
    Inner myinner;
    Outer() : myinner(2) {}
};

struct Outer::Inner
{
    Inner(int n) : num(n) {}
    int num;
};

int main()
{
    Outer myouter;
}

Выдает ошибку error C2079: 'Outer::myinner' uses undefined struct 'Outer::Inner' в VC11.

И почему неработающий код не имеет эффекта, эквивалентного версии, в которой Inner определяется в Outerопределение, как в следующем рабочем коде?

struct Outer
{
    struct Inner
    {
        Inner(int n) : num(n) {}
        int num;
    } myinner;
    Outer() : myinner(2) {}
};

1 ответ

Решение

Это красный флаг, но вы можете сделать это с помощью поддельного шаблона.

template< typename = void >
struct Outer_temp
{
    struct Inner;
    Inner myinner;
    Outer_temp() : myinner(2) {}
};

typedef Outer_temp<> Outer; // Hide template from user.

template< typename v >
struct Outer_temp< v >::Inner
{
    Inner(int n) : num(n) {}
    int num;
};

int main()
{
    Outer myouter;
}

Inner Внутри шаблона находится зависимый тип, поэтому он не должен быть завершенным при определении экземпляра в элементе или любом другом контексте. Он должен быть завершен только после создания экземпляра, в данном случае из main,

Я не могу представить себе вескую причину сделать это, но это так.

Вложенные классы не должны использоваться ради организации программы. Вложенность предполагает концептуальную зависимость: "Внутренний не может существовать, кроме как в контексте, предоставленном Outer". Несмотря на то, что, например, класс контейнера узла обычно является вложенным в контейнер, это может вызвать проблемы. SCARY идиома - это стиль дизайна, который отказывается от такой организации и получает улучшенную универсальность.

TL; DR: определить два класса независимо и связать их с вложенным typedef,

Другие вопросы по тегам