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

概要

设想这样一个场景:我有一个类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的析构函数。
}

知识共享许可协议
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。

posted @ 2016-05-18 11:00  tyusr  阅读(1202)  评论(2编辑  收藏  举报