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()来调用类里面的方法和属性
完成!
04-25 11:15