C++学习笔记14:运算符重载实例之可变长整形数组

1 kebianarr.cpp

/**
 * 运算符重载实例:可变长整型数组
 *
 * 分析:
 *  CArray的对象代表一个数组,需要存放一个数组,那么数组存放在哪?需要使用动态分配的内存来存放数组元素,需要一个对象中有一个指针成员变量指向它。
 *  动态分配内存也需要释放,因此在CArray类的析构函数中进行释放操作
 *
 *  赋值语句中赋值号‘=’需要重载
 *
 *  a2是个对象,但是a2[]跟数组的使用方法一致,因此需要重载运算符[]
 *
 *  CArray的复制构造函数
 *
 *
 * */
#include 
#include "CArray.h"

using namespace std;



int main()  // 要编写可变长整型数组类,使之能如下使用
{
    CArray a;   // 开始里的数组是空的
    for(int i = 0; i < 5; i++)
        a.push_back(i); // 1 要用动态分配的内存来存放数组元素,需要一个指针成员变量。  析构函数中去释放分配的这个内存
    CArray a2, a3;
    a2 = a; // 2 赋值语句的赋值号'='需要重载
    for(int i = 0; i < a.length(); i++)
        cout << a2[i] << " ";   // 3 a2不是一个数组的名字,而是一个对象的名字,因此需要对运算符[]进行重载
    a2 = a3;    // a2是空的
    for(int i = 0; i < a2.length(); ++i)    // a2.length()返回0
        cout << a2[i] << " ";
    cout << endl;
    a[3] = 100;
    CArray a4(a);   // 4 复制构造函数不能使用缺省的,需要自己编写复制构造函数
    for(int i = 0; i < a4.length(); i++)
        cout << a4[i] << " ";
    return 0;
}


2 CArray.h

/**
 * 写一个类考虑构造函数(类型转换构造函数、复制构造函数)、成员函数、析构函数、运算符重载
 * */

#ifndef BEIDALESSON1_CARRAY_H
#define BEIDALESSON1_CARRAY_H
class CArray{
    int size;   // 数组元素的个数
    int* ptr;   // 指向动态分配的数组
public:
    // 普通构造函数
    CArray(int s = 0);  // s 代表数组元素的个数  此处使用了缺省值
    // 复制构造函数
    CArray(CArray& a);
    // 析构函数
    ~CArray();

    // 用来在数组的尾部添加一个元素v
    void push_back(int v);
    // 用于数组对象间的赋值  实现深拷贝的操作
    CArray& operator=(const CArray& n);
    // 返回数组元素个数
    int length();

    // 运算符[]重载为CArray类的成员函数
    // 作用:支持根据下表访问数组元素  例如 n = a[i], a[i] = 4这样的语句
    // 返回C值为int不行!,不支持a[i] = 4; (非引用的函数返回值,不可以作为左值使用!)  a[i]等价于 a.operator[](i);  返回对象a的成员指针ptr指向的动态内存的第i个元素。
    //
    int& operator[](int i);

};
#endif //BEIDALESSON1_CARRAY_H

3 CArray.cpp

//
// Created by z on 19-10-11.
//

#include 
#include "CArray.h"

// 构造函数有一个参数s,代表数组对象被初始化的时候,它里面就已经包含多少个元素了,前面看到s有一个缺省值是0,说明一个数组对象被初始化的时候,没有指定参数s的话,这个参数就是0,数组对象就是空的,没有任何元素。
CArray::CArray(int s):size(s) {
    // 如果s == 0; 说明数组对象是空的,ptr=NULL,代表该数组对象中int* ptr成员指针变量不指向任何地方
    // 如果s不等于0,需要动态分配一片存储空间
    if(s == 0)
        ptr = NULL; // int*型指针不指向任何地方
    else
        ptr = new int[s];   // 将new出来的整形数组的地址付给ptr
}

// 复制构造函数  需要完成深拷贝的工作,需要使得被初始化的那个对象的内容,变成跟a一样,这两个对象不能指向同样的存储空间
/**
 * 为啥要自己写复制构造函数
 * eg:
 *      a1  ptr ------>  11 14 9 8
 *      如果不自己写复制构造函数,执行语句CArray a2(a1);产生效果如下
 *      a2  ptr ------>
 *                       11 14 9 8
 *      a1  ptr ------>
 *      可知,a2对象中ptr指针与a1对象中ptr指针指向同一数组的地址,释放的时候会出现错误。
 *
 *      正确的结果应该是如下,他们指向不同内存空间,但是数组元素一样
 *      a1  ptr ------>  11 14 9 8
 *      a2  ptr ------>  11 14 9 8
 * */
CArray::CArray(CArray &a) {
    // 如果a.ptr是空数组 需要让初始化的这个对象的ptr指针指向的地方也变成一个空数组,size指定0,返回该对象。
    if(!a.ptr)
    {
        ptr = NULL;
        size = 0;
        return;
    }
    // 如果对象a不是空数组,需要将被初始化里面的ptr成员变量指向一片新分配出来的存储空间,存储空间大小与a数组中一致
    ptr = new int[a.size];
    // 将a.ptr所指向的内容,拷贝到需要初始化对象的ptr所指向的地方去,一共拷贝多少个字节的内容,使用sizeof(int) * a.size个
    memcpy(ptr, a.ptr, sizeof(int) * a.size);
    // size成员变量也给赋值一下。
    size = a.size;
}

// 析构函数  释放存储空间,释放之前判断一下ptr是否为空指针,不是空指针,再进行delete
CArray::~CArray() {
    if(ptr)
        delete[] ptr;
}

// 赋值运算符重载函数  返回值为CArray& 目的是为了符合赋值运算符的惯例(在C++中,赋值运算符的返回值是等号左边那个变量的引用)
CArray& CArray::operator=(const CArray &n) {
    // 赋值号的作用是使得‘=’左边对象里存放的数组,大小和内容都和右边的对象一样
    if(ptr == n.ptr)    // 防止 a = a这样的赋值导致出错
        return *this;
    if(n.ptr == NULL)   // 如果n中数组是空的
    {
        // 如果初始化的数组本身不是空的,需要先收回其存储空间
        if(ptr)
            delete[] ptr;
        ptr = NULL;
        size = 0;
        return *this;
    }
    if(size < n.size)   // 如果原有空间够大,就不用分配新的空间
    {
        if(ptr)
            delete[] ptr;
        ptr = new int[n.size];
    }
    memcpy(ptr, n.ptr, sizeof(int) * n.size);
    size = n.size;
    return *this;
}

// 运算符[]重载函数
int& CArray::operator[](int i) {
    return ptr[i];
}

// 数组末尾添加元素v函数
void CArray::push_back(int v) {
    if(ptr)
    {
        int* tmpPtr = new int[size +1]; // 重新分配空间
        memcpy(tmpPtr, ptr, sizeof(int) * size);    // 拷贝原数组内容
        delete[] ptr;
        ptr = tmpPtr;
    }
    else    // 数组本身是空的
        ptr = new int[1];
    ptr[size++] = v;    // 加入新的数组元素
}

// 返回数组长度函数
int CArray::length() {
    return this->size;
}

你可能感兴趣的:(C++)