Попытка скомпилировать приведенный ниже код не удалась из-за «конфликтующего объявления». Почему я не могу определить заранее объявленный класс как этот?
Я сделал это, чтобы скрыть, что реализация использует определенную библиотеку. Хотя я признаю, что это на самом деле ничего не абстрагирует — вам все равно нужно знать, что реализация использует для правильного вызова — я все еще заинтересован в Зачем это не работает
Bar.cpp:
#include "Bar.hpp"#include "Foo.hpp"
using Foo = ns::Foo;
void Bar::foo(Foo f) {
}
Bar.hpp:
class Foo;
class Bar {
void foo(Foo f);
};
Foo.hpp:
namespace ns {
class Foo {
};
}
Чтобы было ясно, я хочу знать, почему нельзя определить ранее объявленный класс с помощью псевдонимов — другими словами, говоря «используйте это определение там, у которого другое имя»
Вы декларируете Foo
дважды с конфликтующими типами. Во-первых, вы объявляете Foo
в Bar.hpp как:
class Foo;
Впоследствии вы объявляете foo в Bar.cpp как:
using Foo = ns::Foo;
Вы не можете поместить прямое объявление таким образом, если вы определили в своем исходном файле псевдоним с тем же именем, потому что тогда вы объявляете два разных типа с одинаковым именем.
Исходя из вашего вопроса, я предполагаю, что вы хотите использовать Foo без его пространства имен в Bar.cpp. Решение заключается в следующем:
Bar.cpp
#include "Bar.hpp"#include "Foo.hpp"
using ns::Foo;
void Bar::foo(Foo f) {}
Bar.hpp
namespace ns
{
class Foo;
}
class Bar
{
void foo(ns::Foo f);
};
Foo.hpp
namespace ns
{
class Foo
{};
}
Потому что для того, чтобы Bar::Foo
чтобы работать, класс Bar должен знать размер аргумента Foo еще до его объявления.
Вы могли бы сделать эту работу, объявив void foo(Foo* f);
Таким образом, вместо того, чтобы знать размер Foo
, компилятор будет заботиться только о размере указателя.
Просто используйте, чтобы выбрать нужное пространство имен:
using namespace ns;