隐藏内联命名空间标头中的私有常量

Rob*_*Rob 28 c++ namespaces

我在头文件中的命名空间中包含一些内联函数,目前无法将它们移动到cpp文件中.其中一些内联函数使用魔术常量,例如:

// Foo.h
namespace Foo
{
    const int BAR = 1234;

    inline void someFunc()
    {
        // Do something with BAR
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我想让这些魔法常数变得私密 - 任何想法如何?我的第一个想法是使用匿名命名空间:

// Foo.h
namespace Foo
{
    namespace
    {
        // 'private' constants here
        const int BAR = 1234;
    }

    inline void someFunc()
    {
        // Do something with BAR
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,Foo::BAR并且可用于包含的任何cpp文件Foo.h?有没有办法在不创建实现cpp文件的情况下执行此操作?

Geo*_*che 30

你不能,匿名命名空间适用于他们定义的翻译单元(或包含在你的情况下).
您可以考虑将它们移动到detail命名空间中,以向用户发出它们是内部详细信息的信号:

namespace foo {
    namespace detail {
        int magic = 42;
    }

    // ... use detail::magic
}
Run Code Online (Sandbox Code Playgroud)

  • 这也是常规提升用途.只要你告诉每个人简单的"从不输入详细名称空间.",大多数人都不会这样做,它的效果很好. (4认同)

vil*_*pam 18

怎么样:

namespace Foo {
    class foo_detail {
    private:
        enum {
            BAR = 1234,
        };

        friend void someFunc();
    };

    inline
    void someFunc() {
        // something with foo_detail::BAR
    }
}
Run Code Online (Sandbox Code Playgroud)

这使得除了您标记为朋友的功能之外,其他任何人都无法访问该常量.您可以使类nonconstructable通过使构造私有,以确保没有人不尝试实例化的类.


小智 5

将它们放在一个特殊的命名空间中或专门命名它们,结合项目约定,这些东西是非公开的:

namespace foo {
  namespace detail { // as in "implementation details"
    inline int answer() { return 42; }
    const int perfect = 28;
  }
  std::string _question(); // not part of foo's "public interface" by convention

  int this_is_public() {
    using namespace detail; // now don't have to prefix detail::
    return answer() + perfect + _question().length();
  }
}
Run Code Online (Sandbox Code Playgroud)

任何使用记录为非公开名称的人都会绕过您尝试的任何“保护”;这突出了真正的问题:记录公共接口的一部分并且可能依赖。

未命名的命名空间解决了一个不同的问题:获取特定 TU 的唯一名称。他们不会在这里帮忙。