C++在C的面向过程概念的基础上提供了面向对象和模板(泛型编程)的语法功能。

下面以一个简单实例(动态数组的简单封装,包括下标的值可以是任意正数值,并提供边界检查)来说明C++是如何实现其逐层抽象的。

1 用结构体实现

// array.h
// array库的接口
#ifndef _array_h
#define _array_h
// 可指定下标范围的数组的存储
struct DoubleArray{
    int low;  
    int high;
    double *storage;
};
// 根据low和high为数组分配空间。分配成功,返回值为true,否则返回值为false
bool initialize(DoubleArray &arr, int low, int high);
// 设置数组元素的值
// 返回值为true表示操作正常,返回值为false表示下标越界
bool insert(const DoubleArray &arr, int index, double value);
// 取数组元素的值
// 返回值为true表示操作正常,返回值为false表示下标越界
bool fatch(const DoubleArray &arr, int index, double &value);
// 回收数组空间
void cleanup(const DoubleArray &arr);
#endif
// array.cpp
// array库的实现
#include "array.h"
#include 
using namespace std;
// 根据low和high为数组分配空间。分配成功,返回值为true,否则返回值为false
bool initialize(DoubleArray &arr, int low, int high)
{
    arr.low = low; 
    arr.high = high;
    arr.storage = new double [high - low + 1];
    if (arr.storage == NULL) 
        return false; 
    else 
        return true;
}
// 设置数组元素的值
// 返回值为true表示操作正常,返回值为false表示下标越界
bool insert(const DoubleArray &arr, int index, double value)
{
    if (index  arr.high) 
        return false;
    arr.storage[index - arr.low] = value;
    return true;
}
// 取数组元素的值
// 返回值为true表示操作正常,返回值为false表示下标越界
bool fatch(const DoubleArray &arr, int index, double &value)
{
    if (index  arr.high) 
        return false;
    value = arr.storage[index - arr.low] ;
    return true;
}
// 回收数组空间
void cleanup(const DoubleArray &arr)
{  
    if (arr.storage)  
        delete [] arr.storage; 
}
// arrayApp.cpp
// array库的应用示例
#include 
using namespace std;
#include "array.h"
int main() 
{
	DoubleArray array; 					// DoubleArray是array库中定义的结构体类型
    double value;
	int low, high, i;
	
    //输入数组的下标范围
	cout <> low >> high;
	
	//初始化数组array,下标范围为20到30
	if (!initialize(array, low, high)) { 
        cout <<"空间分配失败" ; return 1;
    }
	
    for (i = low; i <= high; ++i) { 		// 数组元素的输入
		cout <<"请输入第"<< i <> value;
		insert(array, i, value); 		     // 将value存入数组array的第i个元素
    }
	
    while (true) { 					         // 读取第i个元素
		cout <> i;
		if (i == 0) 
            break;
		if (fatch(array, i, value)) 
            cout << value << endl;
		else 
            cout <<"下标越界n";
    }
	
    cleanup(array);					        //回收存储数组元素的空间
	
    return 0;
}

相关的函数全部有一个结构体函数参数,来操作结构体。通过头文件包括结构体和函数声明来实现模块化并提供接口,实现一个较松散的数据与函数的结合。

而类则不同,类除了提供数据聚合的结构体功能以外,还可以将函数封装进去,通过类名实现名字空间c++模板类c++模板类,并为成员函数提供一个隐含的指向类对象的this指针,使其成员函数能够访问并操作数据成员。

2 用一个不完整的类来模拟结构体实现

// array.h
// 改进后的array接口
#ifndef _array_h
#define _array_h
struct DoubleArray{
    int low;  
    int high;
    double *storage;
    
    // 根据low和high为数组分配空间。分配成功,返回值为true,否则返回值为false
    bool initialize(int lh, int rh);
    
    // 设置数组元素的值
    // 返回值为true表示操作正常,返回值为false表示下标越界
    bool insert(int index, double value);
    
    // 取数组元素的值
    // 返回值为true表示操作正常,返回值为false表示下标越界
    bool fatch(int index, double &value);
    
    // 回收数组空间
    void cleanup();
};
#endif
// array.cpp
// 改进后的array库的实现
#include "array.h"
#include 
using namespace std;
// 根据low和high为数组分配空间。分配成功,返回值为true,否则返回值为false
bool DoubleArray::initialize(int lh, int rh)
{
    low = lh;
    high = rh;
    storage = new double [high - low + 1];
    if (storage == NULL) 
        return false; 
    else return true;
}
// 设置数组元素的值
// 返回值为true表示操作正常,返回值为false表示下标越界
bool DoubleArray::insert(int index, double value)
{   
    if (index  high) 
        return false;
    storage[index - low] = value;
    return true;
}
// 取数组元素的值
// 返回值为true表示操作正常,返回值为false表示下标越界
bool DoubleArray::fatch(int index, double &value)
{
    if (index  high) 
        return false;
    value = storage[index - low] ;
    return true;
}
//回收数组空间
void DoubleArray::cleanup()
{   
    if (storage) 
        delete [] storage; 
}
// arrayapp.cpp
// 改进后的array库的应用示例
#include 
using namespace std;
#include "array.h"
int main()
{
    DoubleArray array;
    double value;
    int low, high, i;
    
    //输入数组的下标范围
    cout <> low >> high;
    
    if (!array.initialize(low, high)) {         // 为array申请存储数组元素的空间
        cout <<"空间分配失败" ; return 1;
    }
    
    //数组array的初始化
    for (i = low; i <= high; ++i) {             //数组元素的输入
        cout <<"请输入第"<< i <> value;
        array.insert(i, value);
    }
    
    while (true) {                              //数组元素的访问
        cout <> i;
        if (i == 0) 
            break;
        if (array.fatch(i, value)) 
            cout << value << endl;
        else 
            cout <<"下标越界n";
    }
    
    array.cleanup();                //归还存储数组元素的空间
    
    return 0;
}

3 用定义较为完整的类来实现

类还实现了资源获取即初始化(RAII, Resource Acquisition Is Initialization)以及自动实现资源析构的功能,以及对运算符的重载等功能。

// DoubleArray.h
// DoubleArray类的定义
#ifndef _array_h
#define _array_h
#include 
class DoubleArray{
    friend ostream &operator<>(istream &is, DoubleArray &obj);
    friend bool operator==(const DoubleArray &obj1, const DoubleArray &obj2);
    
private:
    int low;  
    int high;
    double *storage;
    
public:
    // 构造函数根据low和high为数组分配空间
    DoubleArray(int lh = 0, int rh = 0):low(lh), high(rh)
    {
        storage = new double [high - low + 1]; 
    }	
    
    // 复制构造函数
    DoubleArray(const DoubleArray &arr);   
    
    // 赋值运算符重载函数
    DoubleArray &operator=(const DoubleArray &right);
    
    // 下标运算符重载函数
    double & operator[](int index);              // 作为左值
    const double & operator[](int index) const;  // 作为右值
    
    // 取数组的一部分形成一个新的数组
    DoubleArray operator()(int start, int end, int lh);
    
    // 析构函数
    ~DoubleArray() { 
        if (storage) 
            delete [] storage; 
    }
};
#endif
// DoubleArray.cpp
// DoubleArray类的实现
#include 
#include "DoubleArray.h"
DoubleArray::DoubleArray(const DoubleArray &arr)
{
    low = arr.low; 
    high = arr.high;
    storage = new double [high - low + 1];
    for (int i = 0; i < high -low + 1; ++i)  
        storage[i] = arr.storage[i];
}
DoubleArray &DoubleArray::operator=(const DoubleArray & a)
{
    if (this == &a)                         // 防止自己复制自己
        return *this;
    delete [] storage;                      // 归还空间
    
    low = a.low;  high = a.high;
    storage = new double[high - low + 1];   // 根据新的数组大小重新申请空间
    for (int i=0; i = low && index = low && index <= high); 
    return storage[index - low];
}
ostream &operator<<(ostream &os, const DoubleArray &obj)
{
    os <<"数组内容为:n";
    for (int i=obj.low; i<=obj.high; ++i) 
        os << obj[i] << 't';
    os <>(istream &is, DoubleArray &obj)
{
    cout <<"请输入数组元素["<< obj.low <<", "<< obj.high <<"]:n";
    for (int i=obj.low; i> obj[i] ;
    
    return is;
}
bool operator==(const DoubleArray &obj1, const DoubleArray &obj2)
{
    if (obj1.low != obj2.low || obj1.high != obj2.high) 
        return false;
    for (int i = obj1.low; i<=obj1.high; ++i) 
        if (obj1[i] != obj2[i]) 
            return false;
    return true;
}
DoubleArray DoubleArray::operator()(int start, int end, int lh)
{
    assert (start = low && end <= high );  // 判断范围是否正确
    
    DoubleArray tmp(lh, lh + end - start);                  // 为取出的数组准备空间
    for (int i = 0; i > array1;                      // 利用流提取运算符重载输入array1
    cout <<"array1 "; cout << array1;   // 利用流插入运算符重载输出array1
    
    array2 = array1;                    // 利用赋值运算符重载将array1赋给array2
    
    cout <<"执行 array2 = array1, array2 ";
    cout << array2;
    
    // 利用==重载比较array1和array2
    cout <<"array1 == array2 是 "<< ((array1 == array2)  ? "true" : "false") << endl; 
    
    array2[25] = 0;                      // 利用下标运算符重载为array2的元素赋值
    
    cout <<"执行array[25] = 0后, array1 == array2 是 "
        << ((array1 == array2)  ? "true" : "false") << endl; 
    
    array2 = array1(22, 25, 2);
    cout <<"执行array2 = array1(22, 25, 2)后, array2 的值为: "<< array2;	
    
    while(1);
    return 0;
}

4 用模板实现泛型

强类型一定程度上实现了类型在编译期的检查功能,而模板却可以让类并不囿于过于具体的类型:

// array.h
#include 
// 类模板的友元:重载输入运算符
template 
    class Array;	                                      // 类模板Array的声明
template 
    ostream &operator<<(ostream &os, const Array&obj); // 输出重载声明
template 
class Array {
    friend ostream &operator<<(ostream &os, const Array&obj);
    
private:
    int low;  
    int high;
    T *storage;
    
public:
    // 根据low和high为数组分配空间。分配成功,返回值为true,否则返回值为false
    Array(int lh = 0, int rh = 0):low(lh),high(rh)
    { 
        storage = new T [high - low + 1]; 
    }
    
    // 复制构造函数
    Array(const Array &arr);
    
    // 赋值运算符重载函数
    Array &operator=(const Array & a);
    
    // 下标运算符重载函数
    T & operator[](int index);
    const T & operator[](int index) const;  // 作为右值
    
    // 回收数组空间
    ~Array(){
        if(storage)
            delete [] storage; 
    }  
};
template 
T & Array::operator[](int index)
{
    if (index  high)
    {
        cout <<"下标越界"; 
        return;
    }
    return storage[index - low];
}
template 
const T & Array::operator[](int index) const
{
    if (index  high)
    {
        cout <<"下标越界"; 
        return;
    }
    return storage[index - low];
}
// 类模板的友元:重载输出运算符
template
ostream &operator<<(ostream &os, const Array&obj)
{
    os << endl;
    for (int i=0; i < obj.high - obj.low + 1; ++i) 
        os << obj.storage[i] << 't';
    return os;
}
template
Array::Array(const Array &arr)
{
    low = arr.low; 
    high = arr.high;
    storage = new T [high - low + 1];
    for (int i = 0; i < high -low + 1; ++i)  
        storage[i] = arr.storage[i];
}
template
Array &Array::operator=(const Array & a)
{
    if (this == &a)                         // 防止自己复制自己
        return *this;
    
    delete [] storage;                      // 归还空间
    
    low = a.low;  high = a.high;
    storage = new T[high - low + 1];        // 根据新的数组大小重新申请空间
    for (int i=0; i <= high - low; ++i) 
        storage[i] = a.storage[i];          // 复制数组元素
    
    return *this;
}
// main.cpp
#include 
#include "array.h"
int main()
{
    int start, end;
    cout<>start>>end;
    Array arr(start,end), arr2;
    for(int i = start ; i<= end-start+1 ; i++)
        arr[i] = i*0.9;
    arr[8] = 8.8;
    arr2 = arr;
    cout<<arr2<<endl;
    while(1);
    return 0;
}

-End-

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688