Вопрос по c++ – Как мне переслать объявление внутреннего класса? [Дубликат]

133

Possible Duplicate:
Forward declaration of nested types/classes in C++

У меня есть такой класс ...

<code>class Container {
public:
    class Iterator {
        ...
    };

    ...
};
</code>

В другом месте я хочу передать Container :: Iterator по ссылке, но я не хочу включать файл заголовка. Если я пытаюсь переслать объявление класса, я получаю ошибки компиляции.

<code>class Container::Iterator;

class Foo {
    void Read(Container::Iterator& it);
};
</code>

Компиляция приведенного выше кода дает ...

<code>test.h:3: error: ‘Iterator’ in class ‘Container’ does not name a type
test.h:5: error: variable or field ‘Foo’ declared void
test.h:5: error: incomplete type ‘Container’ used in nested name specifier
test.h:5: error: ‘it’ was not declared in this scope
</code>

Как я могу переслать объявление этого класса, чтобы мне не нужно было включать заголовочный файл, который объявляет класс Iterator?

Я нашел решениеlink bitlixi

Ваш Ответ

3   ответа
117

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

Вам потребуется выполнить одно из следующих действий.

Make the class non-nested Change your declaration order so that the nested class is fully defined first Create a common base class that can be both used in the function and implemented by the nested class.
Это неправильно:en.cppreference.com/w/cpp/language/nested_types
@Nikerboker говорят, что вложенные классы не могут быть объявленыoutside контейнер. Пример в ссылке - прямое объявление вложенного классаinside the definition контейнера, который является другим сценарием.
Вы можете использовать друга, чтобы обойти это, если хотите.
Общий базовый класс - это решение, наиболее часто используемое с моей стороны.
Тот факт, что невозможно заранее объявить вложенную структуру вне контейнера, кажется ограничением в C ++, и это должно быть возможным. Правильно? Есть ли какая-то причина, почему это невозможно?
20

что можно объявить внутренний класс о незавершенных классовых работах (потому что без определения класса невозможно узнать, существует ли на самом делеis внутренний класс). Таким образом, вам нужно будет включить определение контейнера с объявленным вперед внутренним классом:

class Container {
public:
    class Iterator;
};

Затем в отдельном заголовке внедрите Container :: Iterator:

class Container::Iterator {
};

Затем #include только заголовок контейнера (или не беспокойтесь о прямом объявлении и просто включите оба)

Хороший ответ, кроме части в скобках первого абзаца. «Нет способа узнать, существует ли на самом деле внутренний класс». не имеет смысла в этом контексте и сомнительно, чтобы быть точным. Весь смысл прямого объявления заключается в том, что вы сообщаете компилятору о существовании класса (или, в данном случае, внутреннего класса). Это ваше конкретное утверждение будет так же верно для обычных классов и будет означать, что вы не можете объявить что-либо вперед.
1

что вы хотите, но вот обходной путь, если вы готовы использовать шаблоны:

// Foo.h  
struct Foo
{
   export template<class T> void Read(T it);
};
// Foo.cpp
#include "Foo.h"
#include "Container.h"
/*
struct Container
{
    struct Inner { };
};
*/
export template<> 
  void Foo::Read<Container::Inner>(Container::Inner& it)
{

}
#include "Foo.h"
int main()
{
  Foo f;
  Container::Inner i;
  f.Read(i);  // ok
  f.Read(3);  // error
}

Надеюсь, эта идиома может быть вам полезна (и, надеюсь, ваш компилятор основан на EDG и реализует экспорт;)).

Похожие вопросы