这是一个使用命名空间的简单程序。
#include <iostream>
namespace foo {
void hello();
}
void foo::hello() {
std::cout << "hello\n";
}
void foo::hello(); // Why is this syntax allowed? When is it useful?
int main() {
foo::hello();
}
该程序编译良好并产生预期的输出。
$ ./a.out
hello
我想知道void foo::hello();
声明何时有用?在这个程序中,显然这个声明是多余的。但是由于存在这种语法,这在其他情况下必须有用吗?
这是一个例子,表明单独的void foo::hello();
声明是无用的。
// foo.cpp
#include <iostream>
namespace foo {
void hello();
}
void foo::hello() {
std::cout << "foo::hello\n";
}
// main.cpp
void foo::hello(); // This does not work!
int main()
{
foo::hello();
}
尝试编译上述两个文件会导致以下错误:
$ clang++ foo.cpp main.cpp
main.cpp:1:6: error: use of undeclared identifier 'foo'
void foo::hello();
^
main.cpp:5:5: error: use of undeclared identifier 'foo'
foo::hello();
^
2 errors generated.
在上面的示例中修复main.cpp
的唯一方法似乎是包含namespace
声明:
// main.cpp - fixed
namespace foo {
void hello();
}
void foo::hello(); // But now this is redundant again!
int main()
{
foo::hello();
}
因此,在我们正确编译此代码之后,void foo::hello();
声明再次显得多余。是否有任何情况下这样的声明会起到有用的作用?
答案 0 :(得分:2)
在大多数情况下,在C ++中,对于任何可以在未定义或可以完全定义的情况下声明的内容,该事物的声明或定义可以出现在所有相同的上下文中。所以这可能只是保持模式一致的一种方式。
C ++标准并没有竭尽全力禁止其他规则的逻辑结果,但只是没有用,只要相当清楚如果有人这样做将会发生什么。如果它确实添加了这些限制,那么就会给编译器编写者带来额外的工作,而没有真正的好处。
答案 1 :(得分:0)
声明可能会将一个或多个名称引入翻译单元或重新声明先前声明引入的名称。如果是,则声明指定这些名称的解释和属性。
允许这样的代码
#include <iostream>
void foo();
void foo();
void foo();
void foo();
void foo();
int main()
{
foo();
}
void foo() { std::cout << "foo()"; }
有效。拥有一个函数的多个声明没有坏处,只要我们只有一个定义,它就不会引起问题。
另一个例子是你有一个全局函数,你想成为多个类的朋友。您可以在每个类头中包含该函数原型,以便您可以将其与其相关,然后您将在主源文件中包含所有这些类头。所以
A.h
void foo();
struct A { friend void foo(); }
B.h
void foo();
struct B { friend void foo(); }
main.cpp
#include "A.h"
#include "B.h"
...
并将转换为
main.cpp
void foo();
struct A { friend void foo(); }
void foo();
struct B { friend void foo(); }
...
所以我们希望这是合法的。