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

来源:互联网 发布:期货高频交易软件 编辑:程序博客网 时间:2024/06/06 04:50

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;elsereturn 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,, 不是5return 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;elseflag = 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;}


 


 


原创粉丝点击