Only Power Do I Need.

Long-term study, endless practice, strict self-discipline.
随笔 - 16, 文章 - 0, 评论 - 1, 引用 - 0
数据加载中……

(转)谈谈vc如何写dll(封装性,隐藏头文件,私有成员) .

最近项目进行到一定阶段,老板要求把已完成部分分离开并把各模块封装成dll。用vs开发dll当然很简单,是用vs的向导可以很快写一个dll.但是我遇到了一些问题:刚开始只需要把各个模块的头文件和cpp加入到一个新的dll工程,然后又把导出类的成员函数和成员变量用到的结构体类型、类类型定义的头文件加进来,编译后dll就写出来了。问题是当我要使用这个dll时我就得把所有的相关头文件包含到引用dll的工程中。这样显然违背的我写dll的初衷。我认为我写dll的目的主要有两个:一是封装性。我不希望将我算法细节暴露给使用dll的人。因此我想把导出类引用的一些特殊类型(指的是除了简单类型之外的结构体或者类类型)的私有成员隐藏起来,这样就需要把那些头文件还有引用头文件的define语句也隐藏。二是易用性。把我这些dll给别人用时要让他们用起来很方便。如果不加修改的把现在的东西给他们用时需要他们先来熟悉这些特殊类型的定义,比如这些类型数据的初始化等等。而且我的dll引用到的头文件有好几个,而这些头文件又引用了其他头文件。也就是说如果直接提供一个dll我同时还用提供10多个头文件。

在网上我查了很多地方,总结别人的经验,总算把自己的dll封装好了。

    废话一大堆,现在说说我是怎么做的吧。

    现在我有一个导出类BClass,他的成员函数的参数类型和私有成员变量类型都被很多其他头文件所定义,网上提供的一个解决办法是把头文件的define引用语句放到对应的cpp中,这当然是必须的,但是仅仅这样做我们在导出类中使用这些特殊类型的变量只能使用指针。这一点是和dll的特性有关的,原因在于dll只在运行时才被程序加载,在编译时我们无法知道cpp引用头文件里定义的类型。这样如果不使用指针类型变量,由于我们不知道那些类型的变量的大小,在编译时就会报错。所以我们必须把那些非指针型特殊变量改成指针类型。可是如果我们不想这样改的话呢?另外还有缺点就是这样仍然可以让别人知道我的导出类的完整结构,仍然可以略微知道dll开发者的一些细节,封装性仍然不够好。

这样在我的导出类里面还要把一些成员函数和成员变量也给隐藏。容易解决的办法仍然有,把这些函数和变量都从导出类里面拿出来,放到cpp里面作为普通的全局变量和普通函数。这样也可以解决问题但是不是一个好办法,因为这样破坏了类结构(呵呵,曾经有同事直接告诉我不用导出类了,全部改成到处函数得了)。

    问题的解决办法:现有的导出类结构什么都不用改,但是这个类不能作为导出类,在此类的基础上定义他的抽象基类,如IBClass。然后我们把IBClass作为导出类,并且只把我们希望导出的成员函数或者公有变量放在抽象基类里面,把这些函数都作为虚拟函数。那么新的dll我们怎么使用呢,现在只涉及到类的初始化问题以及析构问题。在这里我定义了一个工厂类用来初始化导出类。

现在把过程写出来:

最初的BClass头文件:

#include"CClass.h"
#include
"DClass.h"

class __declspec(dllexport) BClass{

func1(); 
// 这个我希望对dll使用者可见

func2(CClass param1);
//这个我不希望对使用者可见,包括CClass类型以及定义它的头文件CClass.h

DClass param2;
//这个我不希望对使用者可见,包括DClass类型以及定义它的头文件DClass.h
}


因此我的做法是在此基础上添加头文件IBClass.h:

class __declspec(dllexport) IBClass{
virtual func1(); // 这个我希望对dll使用者可见
}


然后我添加了BFactory.h头文件和BFactory.cpp文件
BFactory.h:

#include "IBClass.h"

class BClass;

class __declspec(dllexport) TrackerFactory
{
public:
 
static IBClass *GetB();
 
static void Destroy();
private:
 
static BClass *pB;
}
;

BFactory.cpp:

#include "BClass.h"
#include 
"BFactory.h"

BClass 
*BFactory::pB = 0;

IBClass 
*BFactory::GetB()
{
 
if(!pB)
 
{
  pB 
= new BClass(); 
 }

 
return pB;
}


void BFactory::Destroy()
{
 
if(pB)
  delete pB;
}


转自: http://blog.csdn.net/xiunai78/article/details/4510795#reply

posted on 2011-10-31 21:43 夜舞 阅读(2248) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理