所有C++操作符重载的例子

本文详细介绍了C++中[]、*、赋值、输入输出及!操作符的重载方法及其应用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.[ ]操作符重载

C++语言规定:“[ ]”只能作为类的成员函数进行重载。 “[ ]”是C++中的下标运算符,对于数组或指针来说,下表运算的语义是确定的,不能进行重载。因此,如果看到一个运算结果不是数组或指针的表达式后跟“[ ]”运算符,一定是对“[ ]”进行了重载。

一个例子:

#include <iostream>
using namespace std;

class A
{
	int num[3];
public:
	A();
	int& operator[](int);
};

A::A()
{
	num[0] = 1;
	num[1] = 2;
	num[2] = 3;
}

int& A::operator[](int sub)
{
	cout<<"you are in\n";
	if(sub < 0 || sub >2)
		throw sub;
	else
		return num[sub];
}

int main()
{
	A a;
	A *p = &a;
	try
	{
		for(int i = 0; i < 4; i++)
			//cout<<a[i]<<endl;		//这句和下面的作用一样。 这里也对[]进行了重载
			cout<<p[0][i]<<endl;	//第一个[]运算符是下标运算符的原意,p[0]相当于*p,代表指针所指向的对象
					//第二个[]运算符使用的是重载后的语义,表示从对象内部的成员数组中取数据
	}
	catch(int sub)
	{
		cout<<"subscript out of range:"<<sub<<endl;
	}
	return 0;
};

对 [ ]操作符重载,一般会将操作符函数的返回值定义为引用类型。因为这样找到数组元素后,既可以对它进行读操作,也可以进行写操作。

一般来说,数组下标的数据类型是整数,这是C/C++语言中下标的基本用法。但从语法的角度来说,对operator [] 操作符函数进行重载,并没有限制下标的数据类型,这样就可以在某些特殊的情况下使用特殊的数据类型作为下标,看下面的一个例子,你就没白了。。。。

以字符串作为数组下标:

#include <iostream>
#include <string>
using namespace std;

class Employee
{
	string name;
	string position;
public:
	Employee(string, string);
	string& operator[](string);
};

Employee::Employee(string n, string p)
{
	name = n;
	position = p;
}

string& Employee::operator[](string s)	//以字符串作为参数,而不是整型
{
	if(s == "name")
		return name;
	else if(s == "position")
		return position;
	throw s;
}

int main()
{
	Employee e1("忍者", "经理"), e2("核弹","职员");
	try
	{
		cout<<"e1's name is:"<<e1["name"]<<endl;	//重载了操作符
		cout<<"e1's position is:"<<e1["position"]<<endl;
	}
	catch(string s)
	{
		cout<<"error: not find "<<s<<endl;
	}
	return 0;
}


总结一下 重在operator[] 要注意的几点:

1.操作符函数operator[] 只接受一个参数,没有参数和多于一个参数都会造成编译错误,参数的类型可以是任何类型;

2.操作符函数operator[]返回值类型应该是引用类型,这是为了与传统的数组下标运算语义保持一致;

3.当a为一个数组时,a[i]和i[a]都是合法的,都表示数组a 的下标为i的元素。但是,如果a是一个重载了operator[]的类的对象,那么

i[a]的表示方法将引发编译错误。所以为了显示的表明a是一个数组,在使用下标运算符的时候可采用i[a]的表示方式。

2. *操作符重载

*操作符既可以友元函数的形式重载,也可以以成员函数的形式重载,但如果是后者,应这样定义*操作符函数:

T operator*()

{

return *p;

}   一般情况下重载 * 操作符都是以成员函数的形式进行的。

"*"是一个一元操作符,它作用于指针,表示去指针所指单元的内容。一般来说,对*操作符进行重载的类都含有一个指针。

一个例子:

#include <iostream>
using namespace std;

template<typename T>
class Data
{
	T *ptr;
public:
	Data(T *p)
	{
		ptr = p;
	}
	~Data()
	{
		delete ptr;
	}
	//以友元函数形式重载
	//template<typename T> friend T operator*(const Data<T>&);

	//以成员函数形式重载,,这样比友元函数简洁多了
	T operator*()
	{
		return *ptr;
	}
};

//友元函数
//template<typename T>
//T operator*(const Data<T>& d)
//{
//	return *(d.ptr);
//}

int main()
{
	Data<int> intData(new int(67));
	Data<double> doubleData(new double(22.2));
	cout<<*intData<<endl;	//重载了*操作符
	cout<<*doubleData<<endl;
	return 0;
}


3.赋值操作符重载

两种情况下需要对赋值操作符重载:

1.赋值号两边的表达式类型不一致(且无法进行转换)

2.需要进行“深拷贝”

一个浅拷贝的例子:

#include <iostream>
using namespace std;

class A
{
	int num;
public:
	A()
	{
		num = 0;
	}
	A(int i)
	{
		num = i; 
	}
	void show()
	{
		cout<<num<<endl;
	}
	A& operator= (int i)
	{
		cout<<"you are in operator\n";
		return *this;		//这里只是一个简单的浅拷贝
	}
};

int main()
{
	A a;
	a = 5;	//赋值操作,调用赋值操作符函数,,不过只是钱拷贝
	a.show();	//输出结果为 0,, 不是5
	return 0;
}


一个深拷贝的例子:

#include <iostream>
#include <string>
using namespace std;

class Student
{
	string name;
	int age;
public:
	Student()
	{
		name = "NULL";
	}
	Student(string s, int a)
	{
		name = s;
		age = a;
	}
	//拷贝构造函数
	Student(const Student& s)
	{
		*this = s;	//在这里调用操作符函数 operator=
	}
	void show()
	{
		cout<<"The student's name is:"<<this->name<<endl;
		cout<<"The student's age is:"<<this->age<<endl;
	}
	//实现的是深拷贝
	Student& operator=(const Student& s)
	{
		name = s.name.substr(0, s.name.length());
		age = s.age;
		return *this;
	}
};

int main()
{
	Student s1("张三", 18);
	Student s2("李四", 20);
	s1.show();
	Student s3 = s1;	//这里调用拷贝构造函数,在拷贝函数里面再调用 操作符函数 operator=
	s3.show();
	Student s4;
	s4 = s2;		//这里直接调用操作符函数 operator=
	s4.show();
	return 0;
}

注意要点:

对赋值操作符进行重载是,通常将操作符函数的返回值定义为赋值左操作数类型的引用,这是为了实现表达式的求值,也是为了实现“链式操作”。

4.输入输出操作符重载

输入操作符是>>, 输出操作符是<<,又叫做流对象的“插入操作符”和“提取操作符”。其实这两个操作符最初是在C语言中用于整数的移位操作,到了C++中才利用操作符重载的技术将它们应用于输入、输出操作。

对于基本数据类型的数据类型的输入输出操作都已经在C++标准库中定义好,没有必要重新定义,也不允许重新定义。而对于用户自定义的类来说,如果想利用输入输出操作符进行本类对象的输入输出操作,就需要对>>和<<操作进行重载。

对于输出操作符<<进行重载,只能采用友元函数的形式进行,而不能讲operator<<() 声明为ostream类的成员函数,这是因为,ostream是在C++中标准类库中定义的类,既然是标准库,就不允许用户随意修改。

对于输入操作符>>进行重载,和输出操作符一样,也是只能采用友元函数的形式进行。

输出操作符函数原型: ostream & operator<<(ostream&, const className&)   这里只列出最常用也是最安全的一个

输入操作符函数原型: istream & operator>>(istream&, className&)

一个例子:

#include <iostream>
using namespace std;

class Complex
{
	double real;
	double image;
public:
	Complex(double r = 0.0, double i = 0.0)
	{
		real = r;
		image = i;
	}
	//operator<< 和 operator>> 只能是作为友元函数
	//重载操作符<<
	friend ostream& operator<<(ostream&, const Complex&);
	//重载操作符>>
	friend istream& operator>>(istream&, Complex&);
};

ostream& operator<<(ostream& out, const Complex& c)
{
	out<<"in operator<<\n";
	out<<c.real<<" + "<<c.image<<"i"<<endl;
	return out;	//千万别忘了返回 out
}

istream& operator>>(istream& in, Complex& c)
{
	cout<<"in operator>>\n";
	bool flag = false;
	char ch;
	while(!flag)
	{
		cout<<"please input a complex:";
		in>>c.real;
		in>>ch;
		if(ch != '+')
			continue;
		in>>c.image;
		in>>ch;
		if(ch != 'i')
			continue;
		else
			flag = true;
	}
	return in;	//千万别忘了返回 in
}

int main()
{
	Complex c;
	cin>>c;
	cout<<c;
	return 0;
}


5.!操作符重载

“!”是一个一元操作符,它通常用于布尔量,表示逻辑取反。当在某个类中对 “!”操作符进行重载时,通常表明该类的对象出现了“异常”状况。 可以对”!“操作符进行重载,以表明用new 生成的对象是否构造成功。(new 操作在堆上申请空间)

对operator!进行重载可以有两种方式实现,既可以作为类的成员函数,也可以作为类 的友元函数。

具体情况看下面的例子:

#include <iostream>
using namespace std;

class A
{
	int m;
	char *str1;
	char *str2;
public:
	A(int n, int s1, int s2)
	{
		str1 = new char[s1];
		str2 = new char[s2];
		m = n;
	}
	~A()
	{
		delete str1;
		delete str2;
	}
	void show()
	{
		cout<<m<<endl;
	}

	//重载 ! 操作符, 作为A的成员函数
	//bool operator!()
	//{
	//	cout<<"int operator!()\n";
	//	if(str1&&str2)
	//		return false;
	//	return true;
	//}

	friend bool operator!(const A& a);
};

bool operator!(const A& a)
{
	cout<<"in frined operator!()\n";
	if(a.str1 && a.str2)
		return false;
	return true;
}

int main()
{
	A * p = new A(1, 2, 4);
	if(!p)	//这里只是普通的逻辑取反,并不调用重载函数operator!()
		cout<<"!p\n";
	if(!(*p))		//在这里调用重载函数operator!()
		cout<<"!(*p)\n";
	else 
		p->show();
	delete p;
	return 0;
}


 


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值