关注我之前的question。我已经决定使用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
的使用是否合法,或者这是一个我不小心做的肮脏黑客?
答案 0 :(得分:1)
他们会知道你必须#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
()方法。
同样,您必须从MyClass1
头文件声明实际的mymodule1_fwd.H
类。我在这里使用我自己的个人命名约定,&#34; filename_fwd.H&#34;对于前向声明,前向声明头文件;和&#34; filename.H&#34;对于实际的类实现,实现头文件。
DoSomething
()方法的调用者必须显式#include
MyClass
的实际类声明头文件,因为他们必须将其作为参数传递。< / p>
您无法真正避免调用者必须知道他们实际用于传递参数的类。但只有DoSomething
()方法的调用者才需要它。使用MyClass2
的其他部分并且不调用DoSomething
()的内容,不需要了解MyClass1
的任何内容,并且实际的类声明赢得了&{除非他们明确#include
类实现头文件,否则对他们可见。
现在,如果您仍然需要内联DoSomething
(),出于性能原因,可以使用一些技巧,使用预处理程序指令,如果某人#include
全部是必要的头文件,他们将获得DoSomething
()方法的内联声明。
但那必须是另一个问题。