Круговая зависимость C ++ - пространство имен против структуры - PullRequest
13 голосов
/ 09 февраля 2011

Пожалуйста, просветите меня.Почему это компилируется:

struct compiles
{
    struct A;
    struct B
    {
        B(const A &a) : member(a.member) { }
        int member;
    };
    struct A
    {
        A(const B &b) : member(b.member) { }
        int member;
    };
};

, а это не так:

namespace doesnt
{
    struct A;
    struct B
    {
        B(const A &a) : member(a.member) { }
        int member;
    };
    struct A
    {
        A(const B &b) : member(b.member) { }
        int member;
    };
}

(в MSVC 9.0)

Ответы [ 4 ]

14 голосов
/ 09 февраля 2011

Тело определения class / struct / union обрабатывается одновременно, что позволяет ссылаться на члены классов, определенных позже.namespace обрабатывается сверху вниз, и предварительное объявление struct A не позволяет использовать его элементы без определения.Попробуйте переместить определение конструктора B вне класса, чтобы вы могли поместить его после определения A.

7 голосов
/ 09 февраля 2011

В C ++ область видимости класса особенная.Любое объявление, которое распространяется до или после конца определения класса, автоматически распространяется на области, определенные его определениями членов (3.3.6 [basic.scope.class]).

Это означает, что в первом случаеи первое объявление struct A, и полное определение struct A видны в теле B и его конструкторе.

Это не относится к области имен, поэтому во втором случае a.member в конструкторе B ошибка, потому что определение struct A еще не видно.

3 голосов
/ 09 февраля 2011

[Также протестировано с g ++ 4.2] Первый компилируется, потому что компилятор полностью выбирает все типы, определенные в структуре, перед фактической компиляцией вложенных структур (подумайте об открытых встроенных методах с использованием закрытых атрибутов, которые позже появятся внутри класса). Внутри пространства имен компилятор просто работает сверху вниз и не имеет специальных правил.

0 голосов
/ 09 февраля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...