您可以使用未命名的命名空间来隐藏标头中的常量吗?

问题描述 投票:0回答:3

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

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

    inline void someFunc()
    {
        // Do something with BAR
    }
}

但是,我想将这些神奇常量设为私有 - 有什么想法吗?我的第一个想法是使用匿名名称空间:

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

    inline void someFunc()
    {
        // Do something with BAR
    }
}

但是,这不起作用,并且

Foo::BAR
可用于任何包含
Foo.h
的 cpp 文件吗?有没有办法在不创建实现 cpp 文件的情况下做到这一点?

c++ namespaces unnamed-namespace
3个回答
34
投票

你不能,匿名命名空间适用于它们定义的翻译单元(或包含在你的案例中)。
您可以考虑将它们移动到

detail
命名空间中,以向用户表明它们是内部详细信息:

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

    // ... use detail::magic
}

17
投票

怎么样:

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

        friend void someFunc();
    };

    inline
    void someFunc() {
        // something with foo_detail::BAR
    }
}

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


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();
  }
}

任何使用非公开名称的人都会规避您尝试的任何“保护”;这凸显了真正的担忧:记录公共界面的一部分以及可以依赖的内容。

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

© www.soinside.com 2019 - 2024. All rights reserved.