本文提出了一种设计类的方法,能够降低类之间的依存关系,并减小内存泄露的机会,对外界的接口清晰简洁,在实际工程中很有用。
主要设计思想参考自《Effective C++》:
1.将文件间的编译依存关系降到最低。把要设计的类分成两个类,一个类提供给外界,只定义一些外部接口,不定义成员;另外一个类用于实现内部成员及其函数。这样以“声明依存性”替换“定义依存性”,类内细节有所修改时,客户代码只要重新链接即可,不用重新编译。
2.对指针采用“对象管理”方案。将指针放入到一个类中,这样类的析构函数会自动负责指针的删除,防止了内存泄漏。std::tr1::shared_ptr是一个很不错的选择。
下面是用这种方法设计类的一个例子
假设要设计一个类OutClass供客户使用,那么客户使用时肯定要#include "OutClass.h",里面的内容应该是这样的
<span style="font-size:18px;">//OutClass.h
#pragma once
#include <memory>
class InClass;//这里只声明内部实现类,没有#include "InClass.h"
class OutClass
{
std::tr1::shared_ptr<InClass> MyData;//只有一个指向内部类的智能指针,没有其它成员变量
public:
OutClass(void);
~OutClass(void);
void setID( int id );//这是需要提供给客户使用的接口函数
int getID() const;
};</span>
这个头文件里只有类的声明,没有任何的定义,对OutClass成员函数的定义在OutClass.cpp文件中:
<span style="font-size:18px;">//OutClass.cpp
#include "OutClass.h"
#include "InClass.h"//这里才include InClass.h
#include <iostream>
using namespace std;
OutClass::OutClass(void) : MyData(new InClass)
{
}
OutClass::~OutClass(void)
{
cout << "~OutClass()" << endl;
}
void OutClass::setID( int id )
{
MyData->setID(id);//调用内部类版本的成员函数
}
int OutClass::getID() const
{
return MyData->getID();
}</span>
可以看到OutClass的成员函数也没有任何的实现细节,仅仅是调用InClass的函数而已
下面的InClass才是真正实现OutClass应有功能的类,它包含了所有需要的内部成员及函数,InClass.h文件中的内容如下:
<span style="font-size:18px;">//InClass.h
#pragma once
class InClass
{
int ID;//真正的内部成员
public:
InClass(void);
~InClass(void);
void setID( int id );//与OutClass应有相同的成员函数
int getID() const;
};</span>
注意InClass需要提供与OutClass有相同功能的成员函数,这样能才让OutClass来调用,见InClass.cpp:
<span style="font-size:18px;">//InClass.cpp
#include "InClass.h"
#include <iostream>
using namespace std;
InClass::InClass(void) : ID(0)
{
}
InClass::~InClass(void)
{
cout << "~InClass()" << endl;
}
void InClass::setID( int id )
{
ID = id;
}
int InClass::getID() const
{
return ID;
}</span>
这样一来,当改动了InClass内的实现细节时,对于外界调用OutClass的客户来说是完全不知情的,完全不用把OutClass再重新编译一遍,降低了文件间的依存关系。
测试函数如下:
<span style="font-size:18px;">//main.cpp
#include <iostream>
#include "OutClass.h"
using namespace std;
int main()
{
{
shared_ptr<OutClass> o(new OutClass);
cout << o->getID() << endl;
o->setID(99);
cout << o->getID() << endl;
}
system("pause");
}</span>