// 未排序也没有边界检查
class IntArray{ ... };
// 未排序但支持边界检查
class IntArrayRC{ ... };
// 已排序但没有边界检查
class IntSortedArray{ ... };
#include <IntArray.h>
void swap( IntArray &ia, int i, int j )
{
int tmp = ia[ i ];
ia[ i ] = ia[ j ];
ia[ j ] = tmp;
}
为使IntArray 类能够被继承,我们需要在语法上做一点小小的改变:必须(可选择的)减少封装的层次,
以便允许派生类访问非公有的实现,而且我们也必须显式地指明哪些函数应该是虚拟的。
最重要的变化在于我们如何把一个类设计成为基类。
class IntArray {
public:
// 构造函数
explicit IntArray( int size = DefaultArraySize );
IntArray( int *array, int array_size );
IntArray( const IntArray &rhs );
// 虚拟析构函数!
virtual ~IntArray() { delete [] ia; }
// 等于和不等于操作:
bool operator==( const IntArray& ) const;
bool operator!=( const IntArray& ) const;
IntArray& operator=( const IntArray& );
int size() const { return _size; }
// 去掉了索引检查功能 . . .
virtual int& operator[](int index) { return ia[index]; }
virtual void sort();
virtual int min() const;
virtual int max() const;
virtual int find( int value ) const;
protected:
// 参见13.5 节的说明
static const int DefaultArraySize = 12;
void init( int sz, int *array );
int _size;
int *ia;
};
非公有的成员到底该声明为protected 还是private 类成员是新的设计准则。
为了把一个类设计成基类,要做的第二个设计考虑是找出类型相关的成员函数,并把这些成员函数标记为virtual(虚拟的)。
void init( IntArray &ia )
{
for ( int ix = 0; ix < ia.size(); ++ix )
ia[ ix ] = ix;
}
#ifndef IntArrayRC_H
#define IntArrayRC_H
#include "IntArray.h"
class IntArrayRC : public IntArray {
public:
IntArrayRC( int sz = DefaultArraySize );
IntArrayRC( int *array, int array_size );
IntArrayRC( const IntArrayRC &rhs );
virtual int& operator[]( int );
private:
void check_range( int );
};
#endif
我们无需提供显式的IntArrayRC 析构函数,因为派生类没有引入任何需要析构的数据成员。
继承过来的、需要析构的IntArray 成员都由IntArray 的析构函数来处理。
头文件 IntArrayRC.h中含有 IntArrayRC 的定义,以及在类定义之外定义的 全部内联成员函数的定义。
class IntArray{ ... };
// 未排序但支持边界检查
class IntArrayRC{ ... };
// 已排序但没有边界检查
class IntSortedArray{ ... };
#include <IntArray.h>
void swap( IntArray &ia, int i, int j )
{
int tmp = ia[ i ];
ia[ i ] = ia[ j ];
ia[ j ] = tmp;
}
为使IntArray 类能够被继承,我们需要在语法上做一点小小的改变:必须(可选择的)减少封装的层次,
以便允许派生类访问非公有的实现,而且我们也必须显式地指明哪些函数应该是虚拟的。
最重要的变化在于我们如何把一个类设计成为基类。
class IntArray {
public:
// 构造函数
explicit IntArray( int size = DefaultArraySize );
IntArray( int *array, int array_size );
IntArray( const IntArray &rhs );
// 虚拟析构函数!
virtual ~IntArray() { delete [] ia; }
// 等于和不等于操作:
bool operator==( const IntArray& ) const;
bool operator!=( const IntArray& ) const;
IntArray& operator=( const IntArray& );
int size() const { return _size; }
// 去掉了索引检查功能 . . .
virtual int& operator[](int index) { return ia[index]; }
virtual void sort();
virtual int min() const;
virtual int max() const;
virtual int find( int value ) const;
protected:
// 参见13.5 节的说明
static const int DefaultArraySize = 12;
void init( int sz, int *array );
int _size;
int *ia;
};
非公有的成员到底该声明为protected 还是private 类成员是新的设计准则。
为了把一个类设计成基类,要做的第二个设计考虑是找出类型相关的成员函数,并把这些成员函数标记为virtual(虚拟的)。
void init( IntArray &ia )
{
for ( int ix = 0; ix < ia.size(); ++ix )
ia[ ix ] = ix;
}
#ifndef IntArrayRC_H
#define IntArrayRC_H
#include "IntArray.h"
class IntArrayRC : public IntArray {
public:
IntArrayRC( int sz = DefaultArraySize );
IntArrayRC( int *array, int array_size );
IntArrayRC( const IntArrayRC &rhs );
virtual int& operator[]( int );
private:
void check_range( int );
};
#endif
我们无需提供显式的IntArrayRC 析构函数,因为派生类没有引入任何需要析构的数据成员。
继承过来的、需要析构的IntArray 成员都由IntArray 的析构函数来处理。
头文件 IntArrayRC.h中含有 IntArrayRC 的定义,以及在类定义之外定义的 全部内联成员函数的定义。
如果我们定义了非内联函数,则把它们放在IntArrayRC.C——这个相关联的程序文本文件中。
但是一旦class有一个虚拟函数,该class的每一个对象都将有一个虚拟指针(vptr)指向一个虚拟表格(vtbl),
其中内含该class的所有虚拟函数地址(每个对象有一个vptr,每个class有一个vtbl)。