利用虚函数减少导出DLL的头文件依赖

时间:2023-01-11 16:18:22

概要

设想这样一个场景:我有一个类FunClass,它的声明位于FunClass.h,并且在FunClass.h中,我还引用了secret.h.

现在我需要把FunClass导出成DLL文件供别人二次开发. 这时我需要给别人以下文件:

  • FunClass.h
  • FunClass.lib
  • FunClass.dll
  • secret.h

然而我并不想把secret.h给别人!这个问题可以用一个虚类Fun(名字瞎起的,不重要,Java的风格是IFunClass,然而我们是C++) 来解决。

一个简单的例子

假设我的FunClass有一个方法void A(),和一个依赖secret.h的成员Secret M。那么虚类应当这样写(请为这个虚类新建一个头文件):

////////////////////
//// fun.h
////////////////////
// 请在导出DLL的工程里加上 FUN_EXPORT 预编译指令
#ifndef FUN_EXPORT
#define FUN_API __declspec(dllexport)
#else
#define FUN_API __declspec(dllimport)
#endif // #include something else
// 注意头文件中没有包含 secret.h class FUN_API Fun{
public:
Fun(){};
virtual ~Fun(){}; virtual A() = 0;
// 注意这里没有定义 Secret M
}
FUN_API Fun* createFun();

然后Fun的实现写在Fun.cpp中:

////////////////////
//// fun.cpp
//////////////////// #include "Fun.h"
#include "secret.h"
// #include something else // FunClass 继承自 Fun
class FunClass : public Fun{
public:
FunClass(){};
virtual ~Fun(){}; virtual A();
private:
secret M;
} Fun* createFun(){
return new FunClass();
}; void FunClass::A(){
// A的实现
}

好了!这样就OK了!编译之后会得到Fun.libFun.dll,再加上Fun.h,只需要这三个文件,就能把DLL文件用在其他工程了,下面这段代码是测试:

////////////////////
//// test.cpp
//////////////////// #include "Fun.h" int main(){
Fun* fun = createFun(); // 虽然看起来比较奇怪,但是为了隐藏 secret.h ,忍了!
fun->A(); // fun 指向一个[FunClass类的实例](用F替代吧),
delete fun; // 由于Fun的析构函数是虚函数,所以fun在析构时会自动调用F的析构函数。
}

利用虚函数减少导出DLL的头文件依赖
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。