我正在使用来自不同供应商(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() {}