您的位置:首页 > 编程语言 > C语言/C++

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

2017-01-02 10:40 211 查看

在使用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: