C++ 为什么可以';我不能通过别名来定义一个正向声明的类吗?

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(

由于“声明冲突”,尝试编译下面的代码失败。为什么我不能像这样定义一个前向声明的类

我这样做是为了隐藏实现使用了某个库。虽然我承认这并没有真正抽象出任何东西-您仍然需要知道实现使用什么来进行正确的调用-但我仍然对这为什么不起作用感兴趣

Bar.cpp:

#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之前,还没有定义它。请注意,我想知道