2.14 封装和不完全类型
C和C++代码精粹
好的编程习惯能隐藏用户不必知道的执行细节。例如,要执行一个整数栈,可以为用户提供如下的头文件:
// mystack.h
class StackOfInt ( )
{
public:
StackOfInt ( ) ;
void push ( int );
int pop ( ) ;
int top ( ) const;
int size ( ) const;
private:
enum { MAX_STACK = 100 };
int data [ MAX_STACK];
int stkPtr;
};
因为下面几行的数组和栈指针是私有的,因此用户必须通过你提供的公共接口按照你的方式进行操作(程序清单2.20就是一个例子)。即使成员函数的实现对于用户是隐藏的,但他(或她)可以看一下头文件就很容易地推断出与程序清单2.21相似的内容。如果隐藏所有的实现细节对你来说很重要,你可以通过使用不完全类型增加一个额外的保护层。
不完全类型的大小不能在编译期的时候确定。下面的声明就是一个例子:
extern int a [];
这个声明定义a是一个未知长度的数组,所以不能使用sizeof,否则将得到一个错误信息。这个定义完全不同于:
extern int *a;
这是一个有大小的指针。可以通过在另一个类中隐藏它的实现细节来加强上面栈类型的封装性。在程序清单2.22中,只有一个指向 StackImp的指针出现在StackOfInt的私有部分中。语句
class StackImp;
是StackImp的一个不完全声明,它仅仅表明了类的存在。一旦只有一个StackImp的指针或引用出现在 stack2.h中,用户就不需要stkimp.h。StackOfInt的成员函数目前只是传递请求到StackImp(见程序清单2.23和程序清单2.24)。
程序清单2.20 StackOfInt 的定义
// tstack.cpp: 使用StackOfInt 类
#include <iostream>
#include "mystack.h"
using namespace std;
main()
{
StackOfInt s;
s.push(10);
s.push(20);
s.push(30);
while (s.size())
cout << s.pop() << endl;
}
//输出:
30
20
10
程序清单2.21 StackOfInt 的实现
// stack.cpp: StackOfInt 类的实现
#include "stack.h"
StackOfInt::StackOfInt()
{
stkPtr = 0;
}
void StackOfInt::push(int i)
{
if (stkPtr == MAX_STACK)
throw "overflow";
data[stkPtr++] = i;
}
int StackOfInt::pop()
{
if (stkPtr == 0)
throw "underflow";
return data[--stkPtr];
}
int StackOfInt::top() const
{
if (stkPtr == 0)
throw "underflow";
return data[stkPtr - 1];
}
int StackOfInt::size() const
{
return stkPtr;
}
程序清单2.22 为了更好地封装而使用不完全类型
// stack2.h: 隐藏堆栈的实现
class StackImp;
class StackOfInt
{
public:
StackOfInt();
~StackOfInt();
void push(int);
int pop();
int top() const;
int size() const;
private:
StackImp* imp;
};
程序清单2.23 StackOfInt类的实现
// stack2.cpp
#include "stack2.h"
#include "stkimp.h"
StackOfInt::StackOfInt()
: imp(new StackImp)
{}
StackOfInt::~StackOfInt()
{
delete imp;
}
void StackOfInt::push(int i)
{
imp->push(i);
}
int StackOfInt::pop()
{
return imp->pop();
}
int StackOfInt::top() const
{
return imp->top();
}
int StackOfInt::size() const
{
return imp->size();
}
程序清单2.24 堆栈的实现
// stkimp.cpp
#include "stkimp.h"
StackImp::StackImp()
{
stkPtr = 0;
}
void StackImp::push(int i)
{
if (stkPtr == MAX_STACK)
throw "overflow";
data[stkPtr++] = i;
}
int StackImp::pop()
{
if (stkPtr == 0)
throw "underflow";
return data[--stkPtr];
}
int StackImp::top() const
{
if (stkPtr == 0)
throw "underflow";
return data[stkPtr - 1];
}
int StackImp::size() const
{
return stkPtr;
}
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。
时间: 2024-10-30 17:05:00