类的接口与实现的分离

2008年07月14日 星期一 19:10

类通常的组织方式:接口和实现。

类的接口是指类的声明,实现是指类的成员函数的定义。

在c++程序中,常把接口放在一个与类同名的头文件中,类的实现放在一个与类同名的源程序中。

头文件

以源代码的形式提供给用户,用户可以用#include宏把头文件包含到自己的程序中。

头文件中的信息对用户是可见的,包含:常量定义,类型定义,名字声明,枚举,宏定义,条件编译指令,函数声明,内置函数定义,模板声明或模板定义以及注释等内容。

对于类,常把类的定义放在头文件中,用户可以了解类的全部成员,定义类对象,使用类。

例如:类的定义放在单独的头文件Stack.h中

//堆栈stack的头文件:Stack.h

#ifndef Stack_h #define Stack_h class Stack{ private: int *data; int count; int size; public: Stack(int Stacksize=10); ~Stack(); void Push(int x); int Pop(); int howmany(); }; #endif

源文件

函数或类的实现代码放在源文件中。这样做的好处是,可以把头文件以源代码的方式提供给用户,而源文件则以编译后的目标文件的方式提供给用户,能够达到信息和技术保密的目的,也为多个程序员同时进行软件开发提供了技术支持。

例如:stack类的成员函数的实现放在同名的.cpp文件中。

//堆栈stack的源文件 stack.cpp

#include "stack.h" #include <iostream> using namespace std; Stack::Stack(int stacksize){ if(stacksize>0){    size=stacksize;    data=new int[stacksize];    for(int i=0;i<size;i++)     data[i]=0; } else{    data=0;    size=0; } count=0; }

Stack::~Stack(){ delete []data; }

void Stack::Push(int x){ if(count<size){    data[count]=x;    count++; } else    cout<<"堆栈已满"<<endl; }

int Stack::Pop(){ if(count<=0){    cout<<"堆栈已空"<<endl;    exit(1); } count--; return data[count]; }

int Stack::howmany(){ return count; }

main函数 对类的应用

//应用栈类的主程序:stackmain.cpp

#include "stack.h" #include <iostream> using namespace std; int main() { Stack s1; s1.Push(1); s1.Push(12); s1.Push(32); int x1=s1.Pop(); int x2=s1.Pop(); int c=s1.howmany(); int x3=s1.Pop(); cout<<"howmany:"<<c<<endl; cout<<x1<<"\t"<<x2<<"\t"<<x3<<endl; }

现在我们来研究如何把这三者合到一起,放到同一个项目中。

为了向用户隐藏实现代码,不把类的成员函数的代码暴露给用户,可以把类的实现文件编译成静态链接库(扩展名为.lib的文件),静态链接库由目标代码组成(即二进制代码文件),然后把它与类的头文件一起提供给用户。这样就避免了用户修改成员函数,实现了类接口与实现的分离。

首先,静态链接库的制作:

把stack.cpp制作成静态链接库stack.lib

1.建立目录,目的是为了了解此过程产生的临时文件,如:D:\cpp练习\3.14编程实做,并把stack.h和stack.cpp复制到此目录下。

2。启动vc++6.0,选择“文件。新建”,在工程标签项选择win32 static library,位置编辑处选择上一步新建的目录,工程名字填入:stack 如下图

3。把目录“D:\cpp练习\3.14编程实做”下的源文件stack.cpp添加到此工程中。

此时,工程目前只有一个源文件stack.cpp。

4。编译此工程。编译成功就会在目录“D:\cpp练习\3.14编程实做\stack\Debug”中形成stack.lib静态库文件。

然后是静态库的应用:

1 启动vc++6.0,建立一个简单的应用程序,程序代码如stackmain.cpp,然后把stack.h复制到该应用程序所在的磁盘目录中。

2 编译此程序会产生多个链接错误。

3 选择“工程-设置”,弹出的对话框选择“link”标签。在“L对象/库模块”下面的编辑框的最后输入stack.lib静态库文件所在的磁盘目录。如图:

编译程序,这次就不会有错了。

大功告成!!!

这种方法可以真正实现类的接口与实现的分离。类设计者将类的头文件与实现代码的静态库提供给用户,用户只能通过文件了解类的接口,以及类的成员函数的功能,但他们无法知道个成员函数的实现代码,也就无法修改成员函数的实现代码。

这就使类的封装和信息隐藏更加彻底。

不信,你可以打开stack.dsw文件,你是看不到里面的stack.app文件的内容的。