我正在使用来自不同供应商(C或C ++)的各种库,围绕嵌入式系统(固件级)的许多不同硬件库编写C ++包装器库。头文件公开的API应该与供应商无关......所有供应商头文件库都不包含在我的任何头文件中。
我的一个常见模式是通过仅使用指向某些" unknown"的指针,使供应商成员数据不透明。 vendor struct / class / typedef / pod type。
// 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的类型,我想要的只是将其视为void *
的公共接口(即为指针分配空间,即它),以及实现用正确的指针类型来思考它。
我遇到的两个解决方案是" d-pointer"在Qt中找到的方法,通过替换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总是在我嘴里留下不好的味道。必须有更好的东西。
答案 0 :(得分:1)
如果您愿意选择VendorThingWrapper
的路径,那么您只需允许包装器包含数据本身,而不是指向它的指针。这为您提供了抽象层,避免了额外的取消引用。
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
VendorThing vendorData;
};
... {
vendorDataWrapper->vendorData.doSomething();
}
答案 1 :(得分:1)
您可以使用:
来避免额外的指针取消引用#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() {}