设想这样一个场景:我有一个类 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 国际许可协议进行许可。