C++ 为什么可以';我不能通过别名来定义一个正向声明的类吗?
由于“声明冲突”,尝试编译下面的代码失败。为什么我不能像这样定义一个前向声明的类 我这样做是为了隐藏实现使用了某个库。虽然我承认这并没有真正抽象出任何东西-您仍然需要知道实现使用什么来进行正确的调用-但我仍然对这为什么不起作用感兴趣 Bar.cpp:C++ 为什么可以';我不能通过别名来定义一个正向声明的类吗?,c++,using,forward-declaration,conceptual,C++,Using,Forward Declaration,Conceptual,由于“声明冲突”,尝试编译下面的代码失败。为什么我不能像这样定义一个前向声明的类 我这样做是为了隐藏实现使用了某个库。虽然我承认这并没有真正抽象出任何东西-您仍然需要知道实现使用什么来进行正确的调用-但我仍然对这为什么不起作用感兴趣 Bar.cpp: #include "Bar.hpp" #include "Foo.hpp" using Foo = ns::Foo; void Bar::foo(Foo f) { } class Foo; class Bar { void foo(
#include "Bar.hpp"
#include "Foo.hpp"
using Foo = ns::Foo;
void Bar::foo(Foo f) {
}
class Foo;
class Bar {
void foo(Foo f);
};
namespace ns {
class Foo {
};
}
Bar.hpp:
#include "Bar.hpp"
#include "Foo.hpp"
using Foo = ns::Foo;
void Bar::foo(Foo f) {
}
class Foo;
class Bar {
void foo(Foo f);
};
namespace ns {
class Foo {
};
}
Foo.hpp:
#include "Bar.hpp"
#include "Foo.hpp"
using Foo = ns::Foo;
void Bar::foo(Foo f) {
}
class Foo;
class Bar {
void foo(Foo f);
};
namespace ns {
class Foo {
};
}
为了清楚起见,我想知道为什么不能通过别名来定义以前声明的类,换句话说就是说“使用具有不同名称的定义”,因为为了让
Bar::Foo
工作,Bar类需要在声明Foo参数时就知道它的大小。
您可以通过声明voidfoo(foo*f)来实现这一点代码>
这样,编译器就不会知道Foo
的大小,而只关心指针的大小。
只需使用来选择所需的命名空间:
using namespace ns;
因为为了让Bar::Foo
工作,Bar类需要在声明Foo参数时就知道它的大小。
您可以通过声明voidfoo(foo*f)来实现这一点代码>
这样,编译器就不会知道Foo
的大小,而只关心指针的大小。
只需使用来选择所需的命名空间:
using namespace ns;
您两次声明Foo
,类型冲突。首先,在Bar.hpp中声明Foo
:
class Foo;
随后,您在Bar.cpp中将foo声明为:
using Foo = ns::Foo;
若您在源文件中定义了一个同名的别名,那个么就不能提出这样的转发声明,因为这样您就可以用完全相同的名称声明两个不同的类型
基于您的问题,我假设您希望使用Foo,而在Bar.cpp中不使用其名称空间。解决方案如下:
Bar.cpp
#include "Bar.hpp"
#include "Foo.hpp"
using ns::Foo;
void Bar::foo(Foo f) {}
巴水电站
namespace ns
{
class Foo;
}
class Bar
{
void foo(ns::Foo f);
};
福岛水电站
namespace ns
{
class Foo
{};
}
您两次声明Foo
,类型冲突。首先,在Bar.hpp中声明Foo
:
class Foo;
随后,您在Bar.cpp中将foo声明为:
using Foo = ns::Foo;
若您在源文件中定义了一个同名的别名,那个么就不能提出这样的转发声明,因为这样您就可以用完全相同的名称声明两个不同的类型
基于您的问题,我假设您希望使用Foo,而在Bar.cpp中不使用其名称空间。解决方案如下:
Bar.cpp
#include "Bar.hpp"
#include "Foo.hpp"
using ns::Foo;
void Bar::foo(Foo f) {}
巴水电站
namespace ns
{
class Foo;
}
class Bar
{
void foo(ns::Foo f);
};
福岛水电站
namespace ns
{
class Foo
{};
}
在Bar.hpp中,将Foo向前声明放入适当的命名空间中。它应该work@Slava这一点不正确。我还尝试编译它:“错误:'Foo'尚未声明”@Slava my bad,我忘了在函数参数中限定Foo。在Bar.hpp中,将Foo向前声明放入正确的命名空间中。它应该work@Slava这一点不正确。我还试着编译它:“error:'Foo'没有被声明”@Slava my bad,我忘了在函数参数中限定Foo。但这并不能解决Oebele提到的名称空间问题。为什么不简单地使用:使用名称空间ns代码>而不是使用Foo=ns::Foo
@DimoMarkov我可能不想拉入整个名称空间,例如由于命名冲突。特别是当这个Foo类是我在大型名称空间中使用最多的唯一一个时代码>。这只会引入Foo,而不是名称空间的其余部分ns
。正如@Chiel在他的回答中提到的,您应该在您想要使用它的名称空间中向前声明Foo。Bar类需要有关Foo类型的信息才能声明成员函数。如果不在标头中提供此信息,您的实现将无法同步,因此您将发生冲突。除非像我在回答中提到的那样,用参数foo*声明Bar::foo。但这并不能解决Oebele提到的名称空间问题。为什么不简单地使用:使用名称空间ns代码>而不是使用Foo=ns::Foo
@DimoMarkov我可能不想拉入整个名称空间,例如由于命名冲突。特别是当这个Foo类是我在大型名称空间中使用最多的唯一一个时代码>。这只会引入Foo,而不是名称空间的其余部分ns
。正如@Chiel在他的回答中提到的,您应该在您想要使用它的名称空间中向前声明Foo。Bar类需要有关Foo类型的信息才能声明成员函数。如果不在标头中提供此信息,您的实现将无法同步,因此您将发生冲突。除非像我在回答中提到的那样,用参数foo*声明Bar::foo。为什么类型冲突?这两个都是类,而且在使用语句定义::Foo之前,还没有定义它。请注意,我想知道为什么它除了对修复程序感兴趣之外没有其他作用。首先,您要创建一个typedef,它表示Foo
等于ns::Foo
。稍后,您将把Foo
重新定义为全局命名空间中的一个类。那么什么是Foo呢?只是Foo
,或者ns::Foo
?。我不知道,编译器也不知道。啊,我不知道它算作typedef。我现在有一个类似的例子,库通过using
语句提供模板类的具体版本。如何进行前向声明?只要不省略名称空间,前向声明就不是问题,因为它们变成了使用相同名称进行的不同声明,这会导致冲突。您的答案读得有点向后-您是说Bar.cpp发生在Bar.h之前。为什么类型冲突?这两个都是类,而且在使用语句定义::Foo之前,还没有定义它。请注意,我想知道