我正在为嵌入式系统(固件级别)中的许多不同硬件库编写一个C++包装库,使用来自不同供应商(C或C ++)的各种库。头文件公开的API应该与供应商无关... 所有供应商标头库都未包含在任何我的标头文件中。
我通常采用的一种常见模式是通过仅使用指向某个“未知”供应商结构/类/typedef/pod类型的指针来使供应商成员数据不透明。
在你的cpp文件中。
在实现过程中,
我通常采用的一种常见模式是通过仅使用指向某个“未知”供应商结构/类/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
可能是多种不同的东西。它可以是一个类、结构体、类型或者轻量级对象。我不知道,也不想在头文件中关心这个。但是如果你选择了错误的类型,当供应商头文件和我的头文件一起被包含时,它就不能编译通过。例如,如果这是"vendor.h"
中VendorThing
的实际声明:
typedef struct { int a; int b; } VendorThing;
那么你不能仅仅将VendorThing
声明为class VendorThing;
。我不在乎VendorThing的类型是什么,我只需要公共接口认为它是void *
(即分配指针空间就可以了),而实现使用正确的指针类型。
我遇到的两个解决方案是Qt中发现的“d指针”方法,其中通过替换VendorThing
为新的结构体VendorThingWrapper
来添加一层间接性。
// myclass.h
struct VendorThingWrapper;
class MyClass
{
...
private:
VendorThingWrapper* vendorDataWrapper;
};
在你的cpp文件中。
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
VendorThing* vendorData;
};
... {
vendorDataWrapper->vendorData->doSomething();
}
但这会增加第二个指针的解引用,虽然这不是什么大问题,但由于这是针对嵌入式系统的,我不想因为语言不能实现我想要的而增加这种开销。
另一件事就是将其声明为void。
// myclass.h
class MyClass
{
...
private:
void* vendorDataUntyped;
};
在实现过程中,
//myclass.cpp
#include "vendor.h"
#define vendorData ((VendorThing*)vendorDataUntyped)
... {
vendorData->doSomething();
}
但是#define总是让我感到不舒服。一定有更好的方法。
VendorThing
在头文件中定义,那么这不是pImpl惯用语...在pImpl中,它指向一个仅存在于一个.cpp
文件中的类。这只是对VendorThing的包含。您的第一个建议是pImpl,我认为您夸大了两个间接级别的“问题”。将VendorData
的类型设置为VendorThing
(而不是指针)如何? - M.M