C++ 使用命名空间来避免长路径

标签 c++ namespaces using

我还在学习 C++,之前我从未真正创建过自己的命名空间。我正在对它们进行试验,虽然我可以做大部分事情,但有一件事我似乎仍然做不到。我希望能够在类中调用静态方法,而无需键入类似 NameOfClass::method 的内容。这是我认为代码应该是这样的,但是编译失败:

文件 A.h,

namespace Test
{
    class A
    {
        public:
            static int foo() { return 42; }
    };
}

文件 main.cpp,

#include <iostream>

#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 的自由函数;一般来说,如果你这样做只是为了节省一些输入,那么这是一个坏主意。)

有些人可能建议根本不要使用 using 声明,而是完全限定所有名称。

但这是(引用 Stroustrup 的话)“乏味且容易出错”,并且它妨碍了重构:假设您完全限定类 FooMatic::Stack 的每次使用,然后管理层坚持,就在您之前即将投入生产,您使用 BarMatic 非常相似的 Stack 类,因为 barMatic 刚刚收购了您的公司。

如果你在所有地方都完全合格,你会做很多 grepping,希望你的正则表达式是正确的。如果您使用了 using 声明,则只需修复您的(希望共享的)头文件。这样,using 声明很像“typedef int ourInt;”。或一个明显的常量或常量:“const int FOO = 1;”,因为它提供了一个地方来改变被引用到许多地方的东西。在每次使用时完全限定命名空间会带走这种好处。

相反,如果您使用 using 指令并引入所有 Namespace FooMatic,您的 grep 可能会更难,如果说管理层坚持使用 BarMatic::Foo 但您仍然必须使用 FooMatic:Baz,BarMatic 等同于Baz 因任何原因无法使用。

因此,一次引入一种类型(类、函数、常量)通常是最灵活的,也是最好地保护自己免受不可避免但未知的变化影响的方法。与大多数编码一样,您希望在保持足够粒度的同时尽量减少乏味的重复。

关于C++ 使用命名空间来避免长路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/708089/

相关文章:

javascript - 如何在javascript中调用实例化类的函数?

c++ - using-declaration 不能命名命名空间

c++ - 在公共(public)场合使用 X::func

c++ - 使用 delete 调用析构函数

c++ - 我从使用编译器 c++11 的 uva online judge 那里收到一条错误消息……我不知道为什么会产生这个错误

c++ - 如何修复 : binary = :no operator exists which takes a RHS of const & fullName

autocomplete - 当用作多种类型的静态扩展时限制宏函数的自动完成

java - C++ 和 Java : Use of virtual base class

c++ - 未命名的命名空间

ruby-on-rails - 带有命名空间的自定义设计类的未初始化常量(NameError)