我正在使用来自不同供应商(C或C++)的各种库,围绕嵌入式系统(固件级别)的许多不同硬件库编写C++包装器库。头文件公开的API应该与供应商无关...我的任何头文件中都不包含所有供应商头库。

我有一个常见的模式是通过仅使用指向某些“未知”供应商struct / class / typedef / pod类型的指针,使供应商成员数据不透明。

// myclass.h
class MyClass
{
 ...
private:
   VendorThing* vendorData;
};

和实现(注意:每个实现都是特定于供应商的;所有文件都具有相同的* .h文件)
// myclass_for_vendor_X.cpp
#include "vendor.h"
... {
   vendorData->doSomething();
or
   VendorAPICall(vendorData,...);
or whatever

我的问题是VendorThing可以有很多不同的东西。它可以是类,结构,类型或pod。我不知道,我也不想在头文件中。但是,如果您选择了错误的文件,那么如果同时包含供应商头文件和我的头文件,它将无法编译。例如,如果这是VendorThing中的"vendor.h"的实际声明:
typedef struct { int a; int b; } VendorThing;

然后,您不能仅将VendorThing声明为class VendorThing;。我根本不在乎什么类型的VendorThing,我想要的只是公共(public)接口(interface)将其视为void *(即为指针分配空间,就是这样),而实现则使用正确的方式来考虑它。指针类型。

我遇到的两个解决方案是在Qt中找到的“d-pointer”方法,您可以通过将VendorThing替换为新的结构VendorThingWrapper来添加间接级别
// myclass.h
struct VendorThingWrapper;
class MyClass
{
 ...
private:
   VendorThingWrapper* vendorDataWrapper;
};

并在您的cpp文件中
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
   VendorThing* vendorData;
};

... {
   vendorDataWrapper->vendorData->doSomething();
}

但这增加了第二个指针取消引用,这并不是什么大不了的事情,但是由于这是针对嵌入式系统的,因此我不想因为该语言无法满足我的要求而增加开销。

另一件事就是宣布它无效
// myclass.h
class MyClass
{
 ...
private:
   void* vendorDataUntyped;
};

并在实现中
//myclass.cpp
#include "vendor.h"
#define vendorData ((VendorThing*)vendorDataUntyped)

 ... {
   vendorData->doSomething();
}

但是#define总是在我口中留下难闻的味道。必须有更好的东西。

最佳答案

您可以使用以下方法避免额外的指针取消引用:

#include "vendor.h"

struct VendorThingWrapper : public VendorThing {};

当然,到那时,使用名称MyClassData而不是VendorThingWrapper更有意义。

MyClass.h:
struct MyClassData;

class MyClass
{
   public:

      MyClass();
      ~MyClass();

   private:
      MyClassData* myClassData;
};

MyClass.cpp:
struct MyClassData : public VendorThing {};

MyClass::MyClass() : myClassData(new MyClassData())
{
}

MyClass::~MyClass()
{
   delete myClassData;
}

更新

我能够编译并构建以下程序。未命名的struct没问题。
struct MyClassData;

class MyClass
{
   public:

      MyClass();
      ~MyClass();

   private:
      MyClassData* myClassData;
};


typedef struct { int a; int b; } VendorThing;

struct MyClassData : public VendorThing
{
};

MyClass::MyClass() : myClassData(new MyClassData())
{
   myClassData->a = 10;
   myClassData->b = 20;
}

MyClass::~MyClass()
{
   delete myClassData;
}

int main() {}

10-06 07:53