以自制MyArray对象为例说明对象的概念

本文通过创建自定义的MyArray对象,对比内置数组的不便,展示对象的优势。MyArray提供了安全的下标操作和自然的赋值、比较等运算,展现了对象的鲁棒性和易用性。对象将数据和函数封装,增强代码可读性和维护性,模拟现实世界交互逻辑,是C++编程中的重要概念。

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;
}

main()运行结果
我们发现,我们使用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类和内置数组用起来一样自然,而她又提供了更人性化的输入输出方式,可以使用符合正常逻辑的运算符(=,==,!=,[]),自带下标检查功能,所以她健壮,可重用,使用起来更人性化。

在本例中我们把数据和函数都放在对象中,每个对象都拥有自己的方法和数据。非本对象不能访问本对象的数据,只能通过调用函数与对象交互。现实生活也是这样。每个人知道自己的身高、体重、年龄、性别等信息,其他人想要知道,必须向你搭话:“美女/帅哥,你多大了?”,而不能去派出所调查你的户口。这种交互方式符合现实世界的逻辑,而计算机发明和使用的目的就是模拟现实,解决问题,因此在计算机中使用对象的概念去模拟现实是必然选择。(更重要的是可以让程序看起来更简单,可读性强,容易理解,容易维护。)

对象的使用让函数和数据产生了紧密的联系,让冷冰冰的代码带上了一丝人情味,宛如一栋精装修的别墅,隐藏了内部冰冷的钢筋水泥,通过精心设计的布局和装饰,让人一眼就能感受到房子主人的审美和独特的艺术气息。这便是对象的概念和优点。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值