由于语法规定,不能以运算符来作为函数名,因此C++中规定以operator+符号作为函数名来实现运算。
普通运算符重载
要求:自定义类实现常见的运算符重载
#include<iostream> using namespace std; class Int { int value; public: Int(int x = 0) :value(x) {} Int(const Int& src) :value(src.value) {} Int& operator=(const Int& src)//等号运算符重载 { if (this != &src) { value = src.value; return *this; } } ~Int() {} Int* operator&(){return this;}//取地址重载 const Int* operator&()const { return this; }//对常量的取地址重载 //前置加加重载:先加在返回,代价小 Int& operator++() { value += 1; return*this; } //后置加 :int 只是用来标记区分前置后置加加,无实际作用,代价大 Int operator++(int)//先返回在加 { Int old = *this;//先保存值用于返回 ++* this;//调用前置加加 return old;//返回旧值 } Int operator+(const Int& src)const//对象与对象加 { return Int(value + src.value); } Int operator+(const int num)const//对象与常数相加 { return Int(value + num); } Int& operator+=(const int& src)//加等运算符重载 { this->value+=src.value; return *this; } bool operator==(const Int& src)const// ==运算符重载 { return value == src.value; } bool operator!=(const Int& src)const// !=运算符重载 { return !((*this)== src);//调用 ==运算都重载 } bool operator<(const Int& src)const// <运算符重载 { return value < src.value; } bool operator>=(const Int& src)const // >=运算符重载 { return !(*this < src.value); } bool operator>(const Int& src)const// >运算符重载 { return value > src.value; } bool operator<=(const Int& src)const// <=运算符重载 { return !(*this > src.value); } operator int()const// 整形强转运算符,可将设计的类型中的某值转为内置类型,*this的类型没变。 { return value; } }; Int operator+(const int x, const Int& src)//常数与对象相加,由于参数的限制因此设置为全局函数 { return src + x;//调用对象与常数相加 } int main() { Int a(10), b(0), c(0); c = a + b; c = a + 10; c = 10 + a; b = ++a; //b=a.operator++(); //b=operator(&a); c = a++; //c=a.operator++(0); //c=operator(&a,0); return 0; }
注:
-
自定义类型中的前置加加与优先级无关,把它函数当作函数看待。
-
如果运算符重载的返回值是它本身时,以引用返回。
-
如果返回值是一个将亡值或临时量时,以值返回
-
内置类型需要转化为设计的类型时,由构造函数来进行转换:分显示转换和隐式转换。
-
设计的类型需要转换为内置类型时,需要调用强转运算符重载。
相加运算符重载
要求实现add
括号运算符重载()
class Add { mutable int value;//mutable 易变关键字,使value 在常对象中也可改 public: Add(int x=0):value(x){} int operator()(int a, int b)const//括号运算符重载 { value = a + b; return value; } }; int main() { int a = 10, b = 20, c = 0,d=0; Add add; c = add(a, b);//仿函数,add是对象,调用括号运算符重载 d = Add()(a, b);//构造一个临时量调用括号运算符重载 //c= add.operator()(a,b); return 0; }
要求:设计一个复数的类,进行复数相加运算符重载
#include<iostream> using namespace std; class Complex { private: double Real, Image; public: Complex():Real(0),Image(0){} Complex(double r,double i) :Real(r),Image(i){} Complex operator+(const Complex& c)const //加号运算符重载 //参数:const Complex *const this ,const Complex &c { return Complex(Real + c.Real, Image + c.Image);//调用构造返回,无名构造,系统识别优化会 //直接将其当作将亡值构造在main的栈区 //Complex & Add(const Complex& c)const 如果返回值是引用,会在函数栈区构建一个对象, } //将对象的地址返回,但是当函数栈帧退出,该地址失效,存在风险,不允许返回引用 void Show()const { cout << Real << "+" << Image << "i" << endl; } }; int main() { Complex c1(1.2, 2.3); Complex c2(3.4, 4.5); Complex x = c1 + c2; //相当于 :c3=c1.operator+(c2); //c3=operator+(&c1,c2) x.Show(); }
含指针成员对象运算符重载
-
*运算符重载 :返回所指向的内存
-
->运算符重载:返回指针本身
#include<iostream> using namespace std; class Object { int* ip; public: Object(int* s = NULL) :ip(s) { } ~Object() { if (ip != NULL) { delete ip; } ip = NULL; } int& operator*()//*运算符重载,返回指针的指向 { return *ip; } const int& operator*()const//常方法 { return *ip; } int* operator->()//->运算符重载,返回指针本身 { return ip; //return &**this //即 *this 调用 *运算符重载得到指针的指向 在进行取地址。 } const int* operator->()const//常方法 { return ip; //return &**this; } };
输出流重载
例:进行字符串的类设计
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string.h> using namespace std; class String { char* str; String(char* p, int)//在加重载时,return时直接调用该构造,复制完后自动析构,回收p空间,防止内存泄漏 //int 用于标识区分公有的构造函数,达到重载效果 { str = p; } public: String(const char* p = NULL) :str(NULL) { if (p != NULL) { str = new char[strlen(p) + 1]; strcpy_s(str,strlen(p)+1, p); } else//用来解决当构造对象时是缺省构造时:str=NULL,在赋值如果用来赋值的对象的str==NULL,就会造成系统崩溃 { str = new char[1];//保证str至少在堆区开辟了一个字节的大小。 *str = '\0'; } } String(const String& src):str(NULL) { str = new char[strlen(src.str )+1 ]; strcpy_s(str, strlen(src.str)+1, src.str); } String& operator=(const String& src) { if (this != &src) { delete[] str; str = new char[strlen(src.str )+1]; strcpy_s(str, strlen(src.str )+1, src.str); } return *this; } ~String() { if (str != NULL) { delete[]str; } str = NULL; } ostream& operator<<(ostream& out)const//输出流重载 //ostream& operator<<(const String* const this,ostream& out); { if (str != NULL) { out << str; } return out; } String operator+(const String& src)const { char* p = new char[strlen(this->str) + strlen(src.str) + 1]; strcpy(p, this->str); strcat(p, src.str); return String(p,1);//调用了特殊的私有构造,减小了时间消耗,防止了内存泄漏 } String operator+(const char* s)const { char* p = new char[strlen(this->str) + strlen(s) + 1]; strcpy(p, this->str); strcat(p, s); return String(p, 1);//调用了特殊的私有构造,减小了时间消耗,防止了内存泄漏 //return *this+String(s)//不建议用,有对于的临时量被构建,时间消耗高 } }; String operator+(const char* s, const String& src) { return String(s)+src; } ostream& operator<<(ostream& out, const String& s)//反转输出流重载,不加const:由于括号后的const只能加在this指针 { s << out;//调用输出流重载 s<<cout; //s.operator<<(cout); //operator(&s,cout); return out; } int main() { String s1("hello"); s1 << cout; //s1<<cout; //s1.operator<<(cout); //operator(&s1,cout); cout << s1 << endl; //operator<<(cout,s1) //进入全局函数调用类内输出流重载 String s2(s1); String s3; s1 = s3; cout << s2 << " " << s1 << endl; s1 = "lcx"; String s4("lcx"); s2 = s1 + s4; cout << s2 << endl; s2 = s1 + "hello"; cout << s2 << endl; s2 = "lcx" + s1; cout << s2 << endl; }