我试图转发声明在类中私有使用的一些变量,以限制使用此类时必须包含的标题数。
可悲的是,我要转发的类声明是一个typedef,它是我无法编辑的第三方库(让我们称之为“boost :: asio :: strand”)参数)
这个问题Forward declaration of a typedef in C++证明唯一的解决方案是:
看第二个解决方案,有没有办法可以保护自己免受库中typedef更改的影响,以便编译器在删除/重命名类时使用typedef而不是使用未定义类型它减少了维护头痛?
答案 0 :(得分:0)
如果可能的话,我会尽量不依赖原始课程的前瞻声明。我可能错过了一个案例,但我认为如果类型以某种方式出现在方法签名中,或者如果您的类包含以某种方式指向或引用该类型的成员(可能是间接的),则前向声明仅对纯粹的私人用途有用。 / p>
我建议转发声明类的包装器,并且只在实现文件中定义实际类或typedef已知的时候。
说你的班级标题目前是这样的:
// need header because it contains UglyTypeDef:
#include <UglyHeader.h>
class MyClass {
public:
int theMethod(int a);
private:
void uglyMethod(UglyTypeDef &utd);
int someMember;
UglyTypeDef *utdp;
std::vector<UglyTypeDef *> utds;
};
在这个例子中,我们可以使用前向声明,但我们不想依赖UglyHeader的内部。
我会像这样改变MyClass:
class MyClass {
public:
int theMethod(int a);
private:
// move the private method into the implementation file
// hide the ugly typedef
// we safely forward declare our own private wrapper
struct UglyTypeDefWrapper;
int someMember;
UglyTypeDefWrapper *utdp;
std::vector<UglyTypeDefWrapper *> utds;
};
现在为了使这项工作,cpp文件中的实现也必须改变:
#include "MyClass.hpp"
#include <UglyHeader.h>
struct MyClass::UglyTypeDefWrapper {
// if possible save another level of indirection
// and store by value, otherwise use a second indirection
// by cleverly wrapping at the right level of abstraction
// this abstraction can be free in many cases
UglyTypeDef td;
};
namespace {
// we completely hide the private method in this file as
// an implementation detail and pass it whatever it needs
// this also helps the compiler to inline it,
// because it knows it cannot be referenced in
// a different compilation unit
// we need to pass all members as needed
void uglyFormerMethod(int &someMember, UglyTypeDef &utd) {
someMember += utd.whatever();
}
}
int MyClass::theMethod(int a) {
utd->td.doWhatever();
uglyFormerMethod(someMember, *utd);
for(auto utdwp: utds) {
utdwp->td.doIt();
}
}