首页 > 代码库 > DLL 导出类

DLL 导出类

MyMathFun.h

#pragma once    // #ifdef DLLCLASS_API  // #define DLLCLASS_API _declspec(dllimport)  // #else  // #define DLLCLASS_API _declspec(dllexport)   // #endif    #define DLLCLASS_API _declspec(dllexport)  class DLLCLASS_API MyMathFun  {  public:      MyMathFun(void);      ~MyMathFun(void);      double Add(double a,double b);      double Substract(double a,double b);      double Multiply(double a,double b);      double Divide(double a,double b);  };  

  

MyMathFun.cpp

 

#include "MyMathFun.h"    #include <stdexcept>  using namespace std;  MyMathFun::MyMathFun(void)  {  }  MyMathFun::~MyMathFun(void)  {  }  double MyMathFun::Add(double a,double b)  {      return a+b;  }  double MyMathFun::Substract(double a,double b)  {      return a-b;  }  double MyMathFun::Multiply(double a,double b)  {      return a*b;  }  double MyMathFun::Divide(double a,double b)  {      if (b==0)      {          throw new invalid_argument("b cannot be zero!");      }      return a/b;  }  

  程序调用:

#include <iostream>  using namespace std;  //当使用添加头文件目录,以便程序中包含的头文件存在(即可以找到):  //1.项目,属性->C/C++->常规->附加包含目录:..\MathFunDll  //2.#include "MyMathFun.h"   就可以省略下面的类的再次声明了  #define DLLCLASS_API _declspec(dllimport)  class DLLCLASS_API MyMathFun  {  public:      MyMathFun(void);      ~MyMathFun(void);      double Add(double a,double b);      double Substract(double a,double b);      double Multiply(double a,double b);      double Divide(double a,double b);  };  void main()  {      MyMathFun* mFun=new MyMathFun();      cout<<mFun->Add(1,2)<<endl;//3      cout<<mFun->Substract(3,4)<<endl;//-1      cout<<mFun->Multiply(5,6)<<endl;//30      cout<<mFun->Divide(7,8)<<endl;//0.875  }  

  

需要注意的地方:
1,不直接生成类的实例。对于类的大小,当我们定义一个类的实例,或使用new语句生成一个实例时,内存的大小是在编译时决定的。要使应用程序不依赖于类的大小,只有一个办法:应用程序不生成类的实例,使用DLL中的函数来生成。把导出类的构造函数定义为私有的(privated),在导出类中提供静态 (static)成员函数(如NewInstance())用来生成类的实例。因为NewInstance()函数在新的DLL中会被重新编译,所以总能返回大小正确的实例内存。 
2,不直接访问成员变量。应用程序直接访问类的成员变量时会用到该变量的偏移地址。所以避免偏移地址依赖的办法就是不要直接访问成员变量。把所有的成员变量的访问控制都定义为保护型(protected)以上的级别,并为需要访问的成员变量定义Get或Set方法。Get或Set方法在编译新DLL时会被重新编译,所以总能访问到正确的变量位置。 
3,忘了虚函数吧,就算有也不要让应用程序直接访问它。因为类的构造函数已经是私有(privated)的了,所以应用程序也不会去继承这个类,也不会实现自己的多态。如果导出类的父类中有虚函数,或设计需要(如类工场之类的框架),一定要把这些函数声明为保护的(protected)以上的级别,并为应用程序重新设计调用该虑函数的成员函数。这一点也类似于对成员变量的处理。
所以在创建类指针或者对象时,最好是在类里面的实例函数来创建,下面上一个创建类指针的例子:我这里以类CSetting为例子
首先在类的头文件public下创建函数static CSetting* GetInstace();
接着在类的头文件下面新建private,在里面创建类指针,定义:static CSetting* m_pInstance;
接着在cpp文件中初始化一下指针,一般赋空    CSetting* CSetting::m_pInstance = NULL;(不在构造函数中初始化,放在包含文件下面即可)
在cpp文件的析构函数中,添加指针释放:

CSetting::~CSetting()  {      if(m_pInstance)      {          delete m_pInstance;          m_pInstance = NULL;      }  }  

  

接着最后一步,创建函数GetInstance(),代码如下:

CSetting* CSetting::GetInstace()  {      if(NULL == m_pInstance)      {          m_pInstance = new CSetting;         }      return m_pInstance;  }  

  

在其他程序代用此类的时候可以使用CSetting::GetInstance()来调用类里面的方法和属性
完成!

DLL 导出类