我可以像命名空间一样使用 class 作用域,而不是在所有内容前加上 class 名称吗

Can I use class scope like a namespace instead of prefixing everything with the class name

所以在头文件里面我可以做

namespace X {
    doThis();
}

在实现文件中我可以做到

namespace X {
   doThis() { .... }
}

但是如果我有 class

class X {
    public:
    doThis();
};

我是否可以在实现文件中做这样的事情

class X {
    doThis() { .... }
}

而不是 X::doThis() { .... }?

有“Java hack”¹,您可以在其中“继承”class 以使其成员进入您的命名空间:

class MyUserType : /*protected|private*/ X {

     void foo() {
         doThis(); // works
     }
}

当然这只适用于

  • class 没有定义在继承时会干扰的额外(非静态)特性
  • 您的调用代码在 class 中,可以继承类型
  • 派生的 class 不是模板,因为两阶段查找再次使事情变得奇怪(尽管您可以使用 using 声明来减轻它们,在逐个名称的基础上)

Re: class 定义的静态数据 members/out

在评论中,您似乎主要对代码的简洁性有疑问。调查

Disclaimer: following examples largely copied from cppreference

  1. inline variables (c++17),这是关于命名空间级别的静态变量,同样适用于class成员:

  • constexpr/const 声明中的静态成员初始化。

    如果整数或枚举类型的静态数据成员被声明为 const(而不是 volatile),它可以用一个初始化器初始化,其中每个表达式都是常量表达式,就在 class 定义中:

     struct X
     {
         const static int n = 1;
         const static int m{2}; // since C++11
         const static int k;
     };
     const int X::k = 3;
    
  1. constexpr 成员甚至需要在声明中包含初始化程序:

    struct X {
        constexpr static int arr[] = { 1, 2, 3 };        // OK
        constexpr static std::complex<double> n = {1,2}; // OK
        constexpr static int k; // Error: constexpr static requires an initializer
    };
    
  2. 请注意,在某些情况下,您可能仍然需要 class 定义,但没有初始化程序:

    若 const 非内联 (C++17 起)静态数据成员或 constexpr 静态数据成员 (C++11 起)(C++17² 前)为 odr-used,定义at 命名空间范围仍然是必需的,但它不能有初始化程序。即使冗余 (C++17 起),也可以提供定义。

    struct X {
        static const int n = 1;
        static constexpr int m = 4;
    };
    const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used
    const int X::n;             // … so a definition is necessary
    constexpr int X::m;         // … (except for X::m in C++17)
    

¹ 最长的时间 Java 没有枚举,因此您可以在基础中定义静态常量 class 从中“继承”以获取常量。

² 如果静态数据成员声明为 constexpr,则它是隐式内联的,不需要在命名空间范围内重新声明。这种没有初始化器的重新声明(如上所示以前是必需的)仍然允许,但已弃用。