【问题标题】:Can I use class scope like a namespace instead of prefixing everything with the class name我可以像命名空间一样使用类范围,而不是用类名作为前缀吗
【发布时间】:2020-11-01 01:45:19
【问题描述】:

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

namespace X {
    doThis();
}

在实现文件中我可以做

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

但是如果我有课

class X {
    public:
    doThis();
};

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

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

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

【问题讨论】:

  • No 是简短的回答。一个命名空间可以分成几部分,一个类定义必须作为一个单独的部分出现(尽管类中的各个项目可能在类之外定义)。
  • 因为我需要一个单独的 .cpp 文件,所以我可以设置静态变量
  • 为什么会有这样的问题?
  • @john 好吧,例如,如果有很多静态变量或方法,那么在每个变量的前面都有 MyClass:: 看起来很丑。

标签: c++ class namespaces


【解决方案1】:

有“Java hack”¹,您可以从该类“继承”以将其成员放入您的命名空间:

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

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

当然这只适用于

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

Re:静态数据成员/超出类定义

在 cmets 中,您似乎主要存在代码简洁的问题。看看

免责声明:以下示例大部分抄自 cppreference

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

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

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

     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. 请注意,在某些情况下,您可能仍需要类外定义,但不需要初始化器:

    如果 const 非内联(C++17 起)静态数据成员或 constexpr 静态数据成员(C++11 起)(C++17² 之前)为 odr-used,则命名空间范围内的定义为仍然需要,但它不能有初始化程序。即使是多余的也可以提供定义(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 都没有枚举,因此您需要在基类中定义静态常量并从中“继承”以获取常量。

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

【讨论】:

    猜你喜欢
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2011-09-04
    • 2014-02-02
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    相关资源
    最近更新 更多