Пойдем гулять с бульдогом 🙂
Скажи, у меня есть пространство имен Street::House
(внутри пространства имен Street
) где класс Bulldog
является объявленный (пусть будет в House/Bulldog.hpp
):
namespace Street {
namespace House {
class Bulldog {};
}
}
Тогда у меня есть Bulldog.hpp
:
#include "House/Bulldog.hpp"
namespace Street {
using House::Bulldog;
}
Обратите внимание на то, что происходит: я инъекционных декларация о Street::House::Bulldog
в пространство имен Street
как Street::Bulldog
с using
декларация.
Тогда у меня есть Owner.hpp
где класс Bulldog
является форвард объявил:
namespace Street {
class Bulldog;
class Owner {
Bulldog* bulldog;
};
}
Наконец, у меня есть Owner.cpp
:
#include "Owner.hpp"#include "Bulldog.hpp"
namespace Street {
// Implementation of Owner...
}
Ошибка компиляции происходит в Owner.cpp
:
error: 'Bulldog' is already declared in this scope
Естественным объяснением этого явления является то, что C ++ рассматривает эти 2 Bulldog
классы как разные, но почему? Я не вижу никакой двусмысленности в этом случае, то есть он может действительно работать, если правильно реализован компиляторами.
Какие обходные пути вы можете предложить? Я могу думать только о том, чтобы просто удалить предварительная декларация из Bulldog
от Owner.hpp
и двигаться #include "Bulldog.hpp"
от Owner.cpp
в Owner.hpp
, Тем не менее, это приведет к точному включению, а не предварительная декларация.
Кажется, вы можете исправить это, изменив Bulldog.hpp
сказать
namespace Street {
namespace House {
class Bulldog;
}
using House::Bulldog;
// ...
}
Это работает для меня в Clang.
Owner.hpp
который вы написали как:
namespace Street {
class Bulldog;
class Owner {
Bulldog* bulldog;
};
}
Должен был вместо
namespace Street {
namespace House {
class Bulldog;
}
class Owner {
House::Bulldog* bulldog;
};
}
Вы были случайно объявлены вперед Street::Bulldog
, который не настоящий класс, а не Street::House::Bulldog
, который является настоящий класс. Поэтому ваша реализация в Owner.cpp
был расстроен, потому что Bulldog*
был неоднозначным. Он не знает, имеете ли вы в виду объявленный класс Street::Bulldog
или заявленный (а также определенный, хотя компилятор не заботится об этом) Street::House::Bulldog
,
Так как класс, который вы хотели переслать, объявить Street::House::Bulldog
нужно включить второе, House
пространство имен в вашей декларации в .hpp
файл.