Forward声明了typedef保护

UKM*_*key 5 c++ forward-declaration c++11

我试图转发声明一些仅在类中私下使用的变量,以限制使用此时必须包含的标头数.

可悲的是,我想要转发的类已经证明是一个typedef,它是一个我无法编辑的第三方库(为了论证我们称之为"boost :: asio :: strand")

这个问题在C++中转发typedef的声明 证明了唯一的解决方案是:

  • 只需包含标题并接受它是不可能的
  • 转发声明什么是typedef'ed并添加我自己的typedef

看看第二个解决方案,有没有什么方法可以保护自己免受库中typedef更改的影响,以便编译器在删除/重命名类时使用typedef而不是使用未定义类型,并使其更少维持头痛?

Pau*_*ulR 0

如果可能的话,我会尽量不依赖原始类的前向声明。我可能错过了一个案例,但我认为前向声明仅对纯粹私有用途有用,如果该类型以某种方式出现在方法签名中,或者如果您的类包含以某种方式指向或引用该类型的成员(可能是间接的)。

我建议转发声明该类的包装器,并且仅在已知实际类或 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;
};
Run Code Online (Sandbox Code Playgroud)

在此示例中,我们可以使用前向声明,但我们不想依赖 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;
};
Run Code Online (Sandbox Code Playgroud)

现在为了使这项工作有效,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();
  }
}
Run Code Online (Sandbox Code Playgroud)