C++不建议使用内置数组,提供了功能强大的array和vector。因为内置数组有诸多不便:没有下标越界检查,对两个数组而言不能用==,!=,=等运算符,不能把一个数组赋值给另一个数组等等。而array和vector又有些复杂,自带几十个函数,容易让人看花了眼。为什么我们不自己实现一个精简的数组对象呢?
让我们我们模仿array,创建一个自己的int数组"MyArray"对象。先看看测试和运行效果。
//main()
#include <iostream>
#include "MyArray.h"
using namespace std;
int main()
{
MyArray integers1(3);
MyArray integers2;
cout << integers1;
cout << "类MyArray的对象integers1 长度为"
<< integers1.getSize()
<< "\n初始化后各项值为:\n" << integers1;
cout << "\n类MyArray的对象integers2 长度为"
<< integers2.getSize()
<< "\n初始化后各项值为:\n" << integers2;
cout << "\n\n输入8个数字,用串行cin分别赋值给integers1,integers2两个对象" << endl;
cin >> integers1 >> integers2;
cout << "\n输入后,两对象每个值为:\n"
<< "integers1:\n" << integers1
<< "\nintegers2:\n" << integers2;
cout << "\n\n使用重载的!=(integers1 != integers2)" << endl;
if (integers1 != integers2)
cout << "integers1 != integers2\n" << endl;
MyArray integers3(integers1);
cout << "用拷贝构造函数创建对象integers3\n"
<< "integers3长度为"
<< integers3.getSize()
<< "\n初始化后各个值为\n" << integers3;
cout << "\n\n使用重载的=(integers1 = integers2)" << endl;
integers1 = integers2;
cout << "integers1:\n" << integers1
<< "\nintegers2:\n" << integers2;
cout << "\n\n使用重载的==(integers1 == integers2)" << endl;
if (integers1 == integers2)
cout << "integers1 == integers2" << endl;
cout << "\nintegers1[1] is " << integers1[1];
cout << "\n把1000赋值给integers1[1]" << endl;
integers1[1] = 1000;
cout << "integers1:\n" << integers1;
try
{
cout << "\n\n尝试把1000赋值给integers1[15]" << endl;
integers1[15] = 1000;
}
catch (out_of_range &ex)
{
cout << "出错,发现异常,内容是:" << ex.what() << endl;
}
return 0;
}

我们发现,我们使用MyArray对象起来如此自然、流畅,以至于她和array类一样鲁棒,健壮,好用。
以下是MyArray类的定义和实现:
//MyArray.h
#ifndef MYARRAY_H
#define MYARRAY_H
#include <iostream>
class MyArray
{
friend std::ostream &operator<<(std::ostream &output, const MyArray &ary); //声明为友元,重载<<
friend std::istream &operator>>(std::istream &input, MyArray &ary); //声明为友元,重载>>
public:
explicit MyArray(int len = 5); //构造函数,默认长度为5
MyArray(const MyArray &ary); //自定义拷贝构造函数
~MyArray(); //自定义析构函数
size_t getSize() const; //工具函数,得到对象长度
const MyArray &operator=(const MyArray &ary); //成员函数,重载=
bool operator==(const MyArray &ary) const; //成员函数,重载==
bool operator!=(const MyArray &ary) const; //成员函数,重载!=
int operator[](int at) const; //成员函数,重载[],作为不可修改的右值
int &operator[](int at); //成员函数,重载[],作为可以修改的左值
private:
size_t size; //对象长度
int *ptr; //对象数组的头指针
};
#endif
//MyArray.c
#include <iostream>
#include "MyArray.h"
using namespace std;
ostream &operator<<(ostream &output, const MyArray &ary)
{
for (size_t i = 0; i < ary.getSize(); ++i)
{
output << ary[i] << " ";
}
return output;
}
istream &operator>>(istream &input, MyArray &ary)
{
for (size_t i = 0; i < ary.getSize(); ++i)
{
input >> ary[i];
}
return input;
}
MyArray::MyArray(int length)
:size(length > 0 ? length : throw invalid_argument("数组长度必须大于0")),
ptr(new int[length])
{
for (size_t i = 0; i < size; ++i)
{
ptr[i] = 0;
}
}
MyArray::MyArray(const MyArray &ary)
:size(ary.getSize()),
ptr(new int[size])
{
for (size_t i = 0; i < size; ++i)
{
ptr[i] = ary[i];
}
}
MyArray::~MyArray()
{
delete [] ptr;
}
size_t MyArray::getSize() const
{
return size;
}
const MyArray &MyArray::operator=(const MyArray &ary)
{
if (&ary != this) //避免自我赋值错误
{
if (size != ary.getSize())
{
delete [] ptr;
size = ary.getSize();
ptr = new int[size];
}
for (size_t i = 0; i < size; ++i)
{
ptr[i] = ary[i];
}
}
return *this;
}
bool MyArray::operator==(const MyArray &ary) const
{
if (size != ary.getSize())
{
return false;
}
for (size_t i = 0; i < size; ++i)
{
if (ptr[i] != ary[i])
{
return false;
}
}
return true;
}
bool MyArray::operator!=(const MyArray &ary) const
{
return !(*this == ary);
}
int &MyArray::operator[](int at)
{
if (at >= size || at < 0)
{
throw out_of_range("下标越界");
}
return ptr[at];
}
int MyArray::operator[](int at) const
{
if (at >= size || at < 0)
{
throw out_of_range("下标越界");
}
return ptr[at];
}
我们发现,自创的MyArray类和内置数组用起来一样自然,而她又提供了更人性化的输入输出方式,可以使用符合正常逻辑的运算符(=,==,!=,[]),自带下标检查功能,所以她健壮,可重用,使用起来更人性化。
在本例中我们把数据和函数都放在对象中,每个对象都拥有自己的方法和数据。非本对象不能访问本对象的数据,只能通过调用函数与对象交互。现实生活也是这样。每个人知道自己的身高、体重、年龄、性别等信息,其他人想要知道,必须向你搭话:“美女/帅哥,你多大了?”,而不能去派出所调查你的户口。这种交互方式符合现实世界的逻辑,而计算机发明和使用的目的就是模拟现实,解决问题,因此在计算机中使用对象的概念去模拟现实是必然选择。(更重要的是可以让程序看起来更简单,可读性强,容易理解,容易维护。)
对象的使用让函数和数据产生了紧密的联系,让冷冰冰的代码带上了一丝人情味,宛如一栋精装修的别墅,隐藏了内部冰冷的钢筋水泥,通过精心设计的布局和装饰,让人一眼就能感受到房子主人的审美和独特的艺术气息。这便是对象的概念和优点。
本文通过创建自定义的MyArray对象,对比内置数组的不便,展示对象的优势。MyArray提供了安全的下标操作和自然的赋值、比较等运算,展现了对象的鲁棒性和易用性。对象将数据和函数封装,增强代码可读性和维护性,模拟现实世界交互逻辑,是C++编程中的重要概念。
1773

被折叠的 条评论
为什么被折叠?



