C++第三课-之二(类和对象)

在使用new申请空间的时候,需要及时的delete掉,避免内存泄露。当程序结束的时候,会释放所有使用过的内存

我们用一个可变长的int类型的数组来举一个例子

#include <iostream>


// MyArray 现在的数组很难用 不可变长的数组
// new delete   更改长度时,需要new  copy delete三个步骤的操作
// malloc free relloc   只需要一步就可以了
// new 和 delete是一对,malloc和free是一对,不能混用

class MyArray
{
public:
    // 不需要传递参数的构造函数称为默认构造函数
    // 这个默认构造函数是有问题的,这样会导致每次在AddData的时候,造成_len永远等于0,无法分配内存,导致程序崩溃
    //MyArray()
    //{
    //  _len = 0;
    //  _index = 0;
    //  _data = nullptr;
    //}
    MyArray(const std::size_t len = 10)
    {
        // this指针的使用
        _len = len; // 等价于this->_len = len,下面的都一样,需要说明的是,this指针和类是没有关系的,
                    // this指针和对象是有关系的,this就是一个对象的代名词
        _index = 0;
        _data = new int[len];
    }
    MyArray(const std::size_t len, const int num)
    {
        //MyArray(len);     // error C2082: 形参“len”的重定义
                            // 不能这样调用,因为构造还是有他的调用规则
        //this->MyArray(len);   // “函数样式转换”: 位于“->”运算符右边时非法
                            // 此时用this出问题,是因为对象没有出现
        for (unsigned int i=0; i<len; ++i)
        {
            _data[i] = num;
        }
    }

    ~MyArray()
    {
        if (_data)
            delete[]_data;
    }
    int GetData(const std::size_t index) const // const方法就能被const修饰的对象所调用,但是const对象只能调用const方法
    {                                           // 需要注意的是,在加const的时候,要注意语义,我们不能将AddData的方法改
                                                // 成const的,因为我们明明就是要修改里面的变量的
                                                // const代表的语义是值不能被修改
                                                // 我们不能尝试着让别人(主要是指电脑)来解决自己的错误,还不如自己就不犯这个错误
        // 但是这种访问方式也是有问题的
        if (_len > index)
        {
            return _data[index];
        }
        return 0;
    }
    void SetData(const std::size_t index, const int num)
    {
        if (_len > index)
        {
            _data[index] = num;
        }
    }
    // 获取数组的有效长度
    std::size_t GetLength()
    {
        return _index;
    }
    void AddData(const int num)
    {
        // 不知道需不需要new,有可能还有剩余的空间
        if (_index >= _len)
        {
            _len = _index * 2;
            int *tmp = new int[_len];   // 每次分配_index*2的空间
            memcpy(tmp, _data, _index*sizeof(int)); // 需要注意的是,memcpy是按字节拷贝的,我们应该再乘以类型的长度
            delete[]_data;      // 当越界的时候,delete就会出问题,会出现异常
            _data = tmp;
        }
        _data[_index++] = num;
    }
    void AddData(const MyArray &data)
    {
        for (unsigned int i = 0; i < data._index; ++i)
        {
            // 这个例子主要是想说明私有成员也是可以被访问的,但是访问的条件也是在类的内部前提下,此时就可以编译通过
            // 引申说明了类的访问权限(public、private、protected)以及我们所熟知的const等等,它们都是在编译层面上做检测
            AddData(data.GetData(i));   // error C2662: “int MyArray::GetData(const std::size_t)”: 不能将“this”指针从“const MyArray”转换为“MyArray &”
                                        // this指针,是每一个对象里面的隐藏属性,每一个都会有一个this指针,它们是用来区分不同的对象
            //data.SetData(0, 100);     // 这句话也是错误的,因为它不符合const的语义,它和上面的data.GetData(i)是一样的
                                        // 所以我们也需要将我们的方法也变成一个const的方法,才能被const修饰后所调用
                                        // 那么什么是const方法呢?顾名思义,不会改变方法中的变量的方法称为const方法
        }
    }
    // 直接加一个数组
    void AddData(const int *data, const std::size_t len)
    {
        for (unsigned int i=0; i<len; ++i)
        {
            AddData(data[i]);
        }
    }


    // size_t C风格
    // std::size_t C++风格
    //int &Index(const std::size_t index)
    //{
    //  // 这里需要判断index的值是否越界
    //  if (index < _len)
    //  {
    //      return _data[index];
    //  }
    //  // 这里需要抛出一个异常
    //  // 如果不使用异常体系,那么就需要最原始的Get和Set函数了
    //}

private:
    // 把数据作为私有的,这样会更安全
    // 私有变量在外部是无法使用的,但是在类的内部还是可以使用的
    int *_data;
    std::size_t _len;   // 已经分配的空间
    std::size_t _index; // 已经使用的空间
};


int main()
{
    MyArray array;
    array.AddData(1);
    array.AddData(2);
    array.AddData(3);
    array.AddData(4);
    array.AddData(5);
    array.AddData(6);
    array.AddData(7);
    array.AddData(8);
    array.AddData(10);
    array.AddData(11);
    array.AddData(12);
    array.AddData(13);
    array.AddData(14);
    array.AddData(15);
    array.AddData(16);
    array.AddData(17);
    array.AddData(18);
    array.AddData(19);
    array.AddData(20);
    array.AddData(21);
    array.AddData(22);
    array.AddData(23);
    array.AddData(24);
    array.AddData(25);
    array.AddData(26);
    array.AddData(27);
    array.AddData(28);
    array.AddData(29);
    array.AddData(30);

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值