C++ 方法实现:我可以避免每次都输入 class 名称吗?

C++ method implementations: Can I avoid typing the class name each time?

当我在命名空间 mynamespace 中有 C++ class MyClass 时,我将其方法实现为

void mynamespace::MyClass::method() { … }

我可以将其包装在命名空间中以将单个定义缩短为

namespace mynamespace {

    void MyClass::method() { ... }

}

有没有一种方法可以避免重新输入 MyClass::,这样我就可以在签名更改时更轻松地将 { 之前的所有内容复制到 header 作为原型,不必每次都删除 MyClass::?

我以为"a class is also a namespace, maybe I can do"

namespace mynamespace::MyClass {

    void method() { ... }

}

但这抱怨说我 re-defining MyClass 是另一回事。 using mynamespace::MyClass; 也不起作用(但无论如何都会很糟糕,因为如果它起作用,我将如何在该文件中该行下方的任何位置声明一个独立函数)。

是否有解决方案,或者在 C++ 中根本不可能?

不,合格的 class 名称必须出现在 class 定义之外定义的任何 class 成员上。 (而且只能有一个 class 定义,通常在一个头文件中。)

C++ 标准在 [class.mfct]/4 中阐明了这条规则:

If the definition of a member function is lexically outside its class definition, the member function name shall be qualified by its class name using the ​::​ operator.

并且在 [class.static.data]/2 中对于静态数据成员也类似。

您可以使用预处理器宏来缩写此限定条件,但这会严重损害易读性并且不常见。

没有惯用的方法可以避免这种情况。即使您或其他人可能想出 "hack"(例如,基于宏),它也会降低代码对每个人的可读性。编写 C++ 的正常和预期的方式是成员函数在 class 定义之外定义时具有前面的 MyClass::

我建议寻找一个可以根据命令更新头文件和源文件之间签名的工具。

或者,正如评论所建议的那样,使用 class 定义中的声明提供函数的定义(即提供内联定义)。但这有其自身的缺点。

使用 C++20 模块,您可以在一个文件中实现 class:

module myproject.mymodule;

namespace mynamespace {
    export struct my_class {
        auto my_method() -> int {
            return 8;
        }
    };
}

或者导出整个命名空间片段:

export namespace mynamespace {
    struct my_class {
        auto my_method() -> int {
            return 8;
        }
    };

    auto also_exported() -> void {
        // ...
    }
}

然后,您可以导入该模块,而不是包含它:

import myproject.mymodule;

auto frob() -> void {
    auto my_instance = mynamespace::my_class{};
}