类内的"Using"指令

"Using" directives inside classes

本文关键字:Using 指令      更新时间:2023-10-16

遵循我之前的问题。我已经决定使用 using 指令在我的类中别名类型,以避免导入其他内容并污染使用这些违规标头的其他标头。

namespace MyLibrary {
    namespace MyModule1 {
        class MyClass1 {
        public:
            float X;
            float Y;
            MyClass1(float x, float y): X(x), Y(y) {}
        };
    } // namespace MyModule1
    namespace MyModule2 {
        class MyClass2 {
        private:
            // as suggested in linked question
            using MyCustomType1 = MyLibrary::MyModule1::MyClass1;
        public:
            void DoSomething(MyCustomType1 parameter) {
                std::cout << parameter.X << std::endl;
                std::cout << parameter.Y << std::endl;
            }
        };
    } // namespace MyModule2
} // namespace MyLibrary
int main(int argc, char* argv[])
{
    MyLibrary::MyModule1::MyClass1 some_parameter(1.0f, 2.0f);
    MyLibrary::MyModule2::MyClass2 some_var;
    // Can't do this
    // MyLibrary::MyModule2::MyClass2::MyCustomType1 some_other_var;
    // But I can do this
    some_var.DoSomething(some_parameter);
    return 0;
}

如果 MyLibrary 命名空间在类内(私下(别名,命名空间外部的用户如何知道MyCustomType1是什么?

我在这里使用using合法,还是这是我不小心做的肮脏黑客?

他们会知道,原因很简单,你必须#include两个类的声明。

读了这篇文章和上一个问题,我认为这里缺少的概念是前向声明的概念。

考虑以下头文件,我们将此文件称为mymodule1_fwd.H

namespace MyLibrary {
    namespace MyModule1 {
        class MyClass1;
    } // namespace MyModule1
}

就是这样。这足以让您声明MyClass2

#include "mymodule1_fwd.H"
namespace MyModule2 {
    class MyClass2 {
    private:
        // as suggested in linked question
        using MyCustomType1 = MyLibrary::MyModule1::MyClass1;
    public:
        void DoSomething(MyCustomType1 parameter);
    };
} // namespace MyModule2

请注意,仅包含此头文件不会真正自动获取整个MyModule类声明。另请注意以下事项:

不能定义内联 DoSomething (( 类方法的内容,因为它实际上使用别名类型。这会产生以下后果:

  • 您必须以某种方式在某个地方定义 DoSomething (( 方法,可能是在.C实现转换模块中。

  • 同样,您必须从mymodule1_fwd.H头文件中声明实际的MyClass1类。我在这里使用我自己的个人命名约定,"filename_fwd。H"表示前向声明,前向声明头文件;和"文件名。H"为实际类实现,实现头文件。

  • DoSomething (( 方法的调用者必须显式#include MyClass的实际类声明头文件,因为他们必须将其作为参数传递。

你无法真正避免这样一个事实,即调用方必须知道他们实际用来传递参数的类。但只有 DoSomething (( 方法的调用方需要它。使用MyClass2其他部分并且不调用DoSomething((的东西不需要知道任何关于MyClass1的信息,并且除非他们明确#include类实现头文件,否则实际的类声明对它们不可见。

现在,如果您仍然需要内联 DoSomething ((,出于性能原因,可以使用一些技巧与预处理器指令一起使用,如果有人#include所有必要的头文件,他们将获得 DoSomething (( 方法的内联声明。

但这必须是另一个问题。