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 导出类的更多相关文章

  1. DLL导出类避免地狱问题的完美解决方案

    DLL动态链接库是程序复用的重要方式,DLL可以导出函数,使函数被多个程序复用,DLL中的函数实现可以被修改而无需重新编译和连接使用该DLL的应用程序.作为一名面向对象的程序员,希望DLL可以导出类, ...

  2. DLL的概念、dll导出类(转贴)

    1. DLL的概念DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用.静态链接库与动态链接库的区别:(1)静态链接库与动态链 ...

  3. C++ DLL导出类 知识大全

    在公司使用C++ 做开发,公司的大拿搭了一个C++的跨平台开发框架.在C++开发领域我还是个新手,有很多知识要学,比如Dll库的开发. 参考了很多这方面的资料,对DLL有一个基本全面的了解.有一个问题 ...

  4. [百度空间] [原]DLL导出实例化的模板类

    因为模板是在编译的时候根据模板参数实例化的,实例化之后就像一个普通的类(函数),这样才有对应的二进制代码;否则,没有模板参数,那么编译器就不知道怎么生成代码,所以生成的DLL就没有办法导出模板了.但是 ...

  5. dll的概念 dll导出变量 函数 类

    1. DLL的概念 DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用. 静态链接库与动态链接库的区别:   (1)静态链接 ...

  6. C#调用C++导出类(转)

    由于使用别人的Dll,导出的是一个实体类,在C#里封送很难,百度下,有个朋友回复一篇英文的,虽然不一定使用,但可以作为一个知识点,现把原文贴下: c#调用C++写的dll导出类,包含继承,重载等详细介 ...

  7. DLL导出函数和类的定义区别 __declspec(dllexport)

    DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...

  8. DLL入门浅析(4)——从DLL中导出类

    转载自:http://www.cppblog.com/suiaiguo/archive/2009/07/20/90663.html 前面介绍了怎么从DLL中导出函数和变量,实际上导出类的方法也是大同小 ...

  9. DLL导出函数和类 之 __declspec(dllexport)

    可利用__declspec(dllexport)导出函数或类. 若要指定C类型约定导出,则需在前面加extern “C”. 若要导出函数,__declspec(dllexport) 关键字必须出现在调 ...

随机推荐

  1. stm32驱动DS1302芯片

    天时可以自动调整,且具有闰年补偿功能.工作电压宽达2.5-5.5V.采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力.DS1302的外部引脚分配如下图 ...

  2. Druid的简介及功能

    Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,包括DBCP.C3P0.BoneCP.Proxool.JBoss DataSou ...

  3. Java的内存泄漏

    内存泄漏是指,无用对象(不再使用的对象)持续占用内存或者无用对象的内存得不到及时释放,从而造成的内存浪费 就说是有一块内存你不需要再用了,但是呢你还保留着它的指针,那么这块内存就不会被回收 举个例子 ...

  4. Python 线程池的实现

    import urllib2 import time import socket from datetime import datetime from thread_pool import * def ...

  5. orientationchange

    <!DOCTYPE html> <html> <head> <title>OrientationChange Event Example</tit ...

  6. 除trigger()方法外的jquery手动触发事件

    trigger()可以触发指定事件是大家基本都知道的了. 除了trigger()之外我们也可以这样来触发: html <div id="box" style="he ...

  7. Java 之 web.xml(Java之负基础实战)

    多个web.xml会同时生效,先加载tomcat下的web.xml,再加载网站目录下的web.xml. 1.tomcat自带的web.xml 在tomcat的conf目录下 2.自定义web.xml ...

  8. Angular - - ngReadonly、ngSelected、ngDisabled

    ngReadonly 该指令将input,textarea等文本输入设置为只读. HTML规范不允许浏览器保存类似readonly的布尔值属性.如果我们将一个Angular的插入值表达式转换为这样的属 ...

  9. jquery换肤

    <script src="script/jquery-2.1.0.js"></script>      <link href="style/ ...

  10. MFC中在基于对话框的窗体中使用CFileDialog导致菜单栏变灰的解决方案

    CSDN的博客编辑器实在是难用……转战博客园 直接把CSDN发的搬过来了 ————————————————————————————我是分割线———————————————————————————— 第 ...