DLL 导出类

Posted 、张念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 导出类的主要内容,如果未能解决你的问题,请参考以下文章

将基于 QObject 的类导出到 DLL

如何调用DLL中的导出类

从 DLL 导出类

从 C++ dll 导出一个类?

在 VC++ 中,有没有办法知道没有任何头文件的 dll 的导出类?

重组类以从 dll 导出类