我还在学习C++,之前我从未真正创建过自己的命名空间.我正在试验它们,当我得到大部分工作时,有一件事我似乎无法做到.我希望能够在类中调用静态方法而无需键入类似的东西NameOfClass::method
.这是我认为代码应该是什么样子,但它无法编译:
档案A.h
,
namespace Test { class A { public: static int foo() { return 42; } }; }
档案main.cpp
,
#include#include "A.h" using namespace std; using namespace Test::A; int main() { cout << foo() << endl; return 0; }
编译器给了我:
main.cpp:6: error: ‘A’ is not a namespace-name main.cpp:6: error: expected namespace-name before ‘;’ token main.cpp: In function ‘int main()’: main.cpp:10: error: ‘foo’ was not declared in this scope
没有打字就可以做我想做的事A::foo
吗?
在C++中,您/尤其/必须仔细阅读编译器错误消息.
请注意,第一个错误是"错误:'A'不是命名空间名称".这是真的,A是一个类名.
using namespace Foo; // brings in all of foo; using Bar::Baz // brings in only Baz from Bar
你想写:
using Test::A;
这样做有两个好处:它带来了A供你使用,它并没有带来所有其余的Test,这也很好,因为你应该只带入你需要的东西,以免意外地依赖你没有意识到自己依赖的东西.
但是,由于foo在A中是静态的,因此您仍然必须明确地引用A :: foo.(除非你做一些像写一个转发到A :: foo的免费函数的东西;一般来说,如果你只是为了节省一些打字,这是一个坏主意.)
有些人可能会建议不要使用声明,而是完全限定所有名称.
但这是(引用Stroustrup)"乏味且容易出错",并且它妨碍了重构:说你完全符合FooMatic :: Stack类的每一次使用,然后管理层坚持,就在你即将到来之前去生产,你使用BarMatic非常相似的Stack类,因为barMatic刚收购了你的公司.
如果你在任何地方完全合格,你会做很多的捣蛋,希望你的正则表达式是正确的.如果您使用了using声明,则可以修复您的(希望共享的)头文件.这样,using声明很像"typedef int ourInt".或者一个清单常量或const:"const int FOO = 1;",因为它提供了一个地方来改变被引用到许多地方的东西.在每次使用时完全限定命名空间都会带来好处.
相反,如果您使用了using指令并引入了所有Namespace FooMatic,那么你的grep可能会更难,如果说管理层坚持使用BarMatic :: Foo但是你仍然必须使用FooMatic:Baz,Baz的BarMatic等价物就是无论什么原因无法使用
因此,一次引入一种类型(类,函数,常量)通常是最灵活的,最好地保护自己免受不可避免的但尚未知的变化.与大多数编码一样,您希望在保持足够粒度的同时最大限度地减少繁琐的重复.
没有办法解决它需要为静态方法指定类名.
using namespace Test;
然后:
int answerToEverything = A::foo();