16运算符重载
来源:互联网 发布:免费婚恋交友软件 编辑:程序博客网 时间:2024/06/06 12:35
运算符重载
- 运算符重载
- 概念
- 限制
- 基础
- 提高
- 字符串类的实现
- 附录运算符和结合性
本人博客收集自网上前人资料,只为做笔记复习,而且好的东西应该和大家分享才是!如有冒犯,告知鄙人定会删除
1.概念
- 什么是运算符重载
所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,因此,一个函数名就可以用来代表不同功能的函数,也就是”一名多用”。
运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。例如,大 家都已习惯于用加法运算符”+”对整数、单精度数和双精度数进行加法运算,如5+8, 5.8 +3.67等,其实计算机对整数、单精度数和双精度数的加法操作过程是很不相同的, 但由于C++已经对运算符”+”进行了重载,所以就能适用于int, float, doUble类型的运算。
又如”<<“是C++的位运算中的位移运算符(左移),但在输出操作中又是与流对 象cout 配合使用的流插入运算符,”>>“也是位移运算符(右移),但在输入操作中又是与流对象 cin 配合使用的流提取运算符。这就是运算符重载(operator overloading)。C++系统对”<<“和”>>“进行了重载,用户在不同的场合下使用它们时,作用是不同 的。对”<<“和”>>“的重载处理是放在头文件stream中的。因此,如果要在程序中用”<< “和”>>”作流插入运算符和流提取运算符,必须在本文件模块中包含头文件stream(当然还应当包括”using namespace std“)。
现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。?
- 运算符重载入门技术推演
- 为什么会用运算符重载机制
用复数类举例Complex c3 = c1 + c2;
原因 Complex是用户自定义类型,编译器根本不知道如何进行加减.因此编译器给提供了一种机制,让用户自己去完成,自定义类型的加减操作。这个机制就是运算符重载机制 - 运算符重载的本质是一个函数
- 为什么会用运算符重载机制
#include <iostream>using namespace std;class Complex{public: int a; int b;public: Complex(int a=0, int b=0) { this->a = a; this->b = b; } void printCom() { cout<<a<<" + " << b << "i" <<endl; }};//1 定义了全局函数Complex myAdd(Complex &c1, Complex &c2){ Complex tmp(c1.a + c2.a, c1.b+ c2.b); return tmp; //}//2 函数名 升级Complex operator+(Complex &c1, Complex &c2){ cout<<"12345上山 打老虎"<<endl; Complex tmp(c1.a + c2.a, c1.b+ c2.b); return tmp; //}int main(){ int a = 0, b = 0; int c; c = a + b; //1 基础数据类型 编译器已经知道了. 如何运算 // a + bi 复数运算规则 Complex c1(1, 2), c2(3, 4); Complex c3; //2 类 也是一种数据类型 用户自定义数据类型 C++编译器 是不知道如何进行运算 //c3 = c1 + c2 ; //c1--; --c1 //3 c++编译器应该给我们程序员提供一种机制 ... //让自定义数据类型 有机会 进行 运算符操作 ====> 运算符重载机制 //4 运算符重载机制 //步骤1 普通函数 //Complex c4 = myAdd(c1, c2); //c4.printCom(); //步骤2 operator+ 函数名称 //Complex c4 = c1 + c2 //Complex c4 = operator+(c1, c2); //c4.printCom(); //步骤3 +替换 函数名 Complex c4 = c1 + c2; c4.printCom(); //步骤3 //Complex c4 = c1 / c2; //c4.printCom(); //总结: 1 运算符重载的本质 是 函数调用 cout<<"hello..."<<endl; return 1;}
2.限制
3.基础
例如:
//全局函数 完成 +操作符 重载Complex operator+(Complex &c1, Complex &c2)//类成员函数 完成 -操作符 重载Complex operator-(Complex &c2)
- 运算符重载的两种方法
例如1:通过类成员函数完成-操作符重载
//函数声明 Complex operator-(Complex &c2)//函数调用分析//用类成员函数实现-运算符重载 Complex c4 = c1 - c2; c4.printCom(); //c1.operator-(c2);
例如2:通过全局函数方法完成+操作符重载
//函数声明 Complex operator+(Complex &c1, Complex &c2) //函数调用分析int main(){ Complex c1(1, 2), c2(3, 4); //Complex c31 = operator+(c1, c2);Complex c3 = c1 + c2; c3.printCom();}
例如3
//前置++操作符 用全局函数实现 Complex& operator++(Complex &c1) { c1.a ++; c1.b ++; return c1; }
//调用方法 ++c1 ; //=需要写出操作符重载函数原形
c1.printCom();
//运算符重载函数名定义
//首先承认操作符重载是一个函数 定义函数名operator++
//分析函数参数 根据左右操作数的个数,operator++(Complex &c1)
//分析函数返回值Complex& operator++(Complex &c1)
返回它自身
例如4
//4.1前置—操作符 成员函数实现Complex& operator--(){ this->a--; this->b--; return *this;}
//4.2调用方法
--c1;
c1.printCom();
//4.3前置—运算符重载函数名定义
//c1.operator–()
例如5
//5.1 //后置++ 操作符 用全局函数实现Complex operator++(Complex &c1, int) { Complex tmp = c1; c1.a++; c1.b++; return tmp;}
//5.2 调用方法 c1 ++ ; //先使用 后++
//5.3 后置++运算符重载函数名定义
Complex operator++(Complex &c1, int)
函数占位参数 和 前置++ 相区别
例如6
//6.1 后置— 操作符 用类成员函数实现 Complex operator--(int) { Complex tmp = *this; this->a--; this->b--; return tmp; }
//6.2 调用方法 c1 ++ ; //先使用 后++
//6.3 后置–运算符重载函数名定义
Complex operator--(int)
//函数占位参数 和 前置– 相区别
前置和后置运算符总结
C++中通过一个占位参数来区分前置运算和后置运算
#include <iostream>using namespace std;class Complex{private: int a; int b; //全局函数 重载+运算符 friend Complex operator+(Complex &c1, Complex &c2); //重载 前置++ friend Complex& operator++(Complex &c1); friend Complex operator++(Complex &c1, int);public: Complex(int a=0, int b=0) { this->a = a; this->b = b; } void printCom() { cout<<a<<" + " << b << "i" <<endl; }public: //成员函数法 实现 -运算符重载 Complex operator-(Complex &c2) { Complex tmp(this->a - c2.a, this->b - c2.b); return tmp; } //前置-- Complex& operator--() { this->a --; this->b --; return *this; } //后置-- Complex operator--(int) { Complex tmp = *this; this->a--; this->b--; return tmp; }};//全局函数法 实现 + 运算符重载Complex operator+(Complex &c1, Complex &c2){ Complex tmp(c1.a + c2.a, c1.b + c2.b); return tmp;}//前置++Complex& operator++(Complex &c1){ c1.a++; c1.b++; return c1;}//后置++Complex operator++(Complex &c1, int){ //先使用 在让c1加加 Complex tmp = c1; //return c1; c1.a ++; c1.b ++; return tmp;}/*全局函数、类成员函数方法实现运算符重载步骤 1)要承认操作符重载是一个函数,写出函数名称 2)根据操作数,写出函数参数 3)根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务*/void main(){ Complex c1(1, 2), c2(3, 4); //1 全局函数法 实现 + 运算符重载 // Complex operator+(Complex &c1, Complex &c2); Complex c3 = c1 + c2; c3.printCom(); //2 成员函数 法 实现 -运算符重载 //c1.operator-(c2); //Complex operator-(Complex &c2) Complex c4 = c1 - c2; c4.printCom(); //前置++操作符 用全局函数实现 ++c1; c1.printCom(); //前置--操作符 成员函数方法 --c1; c1.printCom(); //Complex& operator++(Complex &c1) //c1.operator--(); //后置++操作符 用全局函数实现 c1++; c1.printCom(); //后置--操作符 用成员函数实现 c1--; c1.printCom(); //c1.operator--() cout<<"hello..."<<endl; system("pause"); return ;}
定义运算符重载函数名的步骤
全局函数、类成员函数方法实现运算符重载步骤
1)要承认操作符重载是一个函数,写出函数名称operator+ ()
2)根据操作数,写出函数参数
3)根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务
运算符重载的正规写法
#include <iostream>using namespace std;/*class ostream{};*/class Complex{private: int a; int b; //friend void operator<<(ostream &out, Complex &c1); friend ostream& operator<<(ostream &out, Complex &c1);public: Complex(int a=0, int b=0) { this->a = a; this->b = b; } void printCom() { cout<<a<<" + " << b << "i" <<endl; }public: //实现 + 运算符重载 Complex operator+(Complex &c2) { Complex tmp(a + c2.a, b + c2.b); return tmp; } //前置++ Complex& operator++() { a++; b++; return *this; } //后置++ Complex operator++(int) { //先使用 在让c1加加 Complex tmp = *this; //return c1; this->a ++; this->b ++; return tmp; } //成员函数法 实现 -运算符重载 Complex operator-(Complex &c2) { Complex tmp(this->a - c2.a, this->b - c2.b); return tmp; } //前置-- Complex& operator--() { this->a --; this->b --; return *this; } //后置-- Complex operator--(int) { Complex tmp = *this; this->a--; this->b--; return tmp; }};void main31(){ Complex c1(1, 2), c2(3, 4); //1 全局函数法 实现 + 运算符重载 // Complex operator+(Complex &c1, Complex &c2); Complex c3 = c1 + c2; c3.printCom(); //2 成员函数 法 实现 -运算符重载 //c1.operator-(c2); //Complex operator-(Complex &c2) Complex c4 = c1 - c2; c4.printCom(); //前置++操作符 用全局函数实现 ++c1; c1.printCom(); //前置--操作符 成员函数方法 --c1; c1.printCom(); //Complex& operator++(Complex &c1) //c1.operator--(); //后置++操作符 用全局函数实现 c1++; c1.printCom(); //后置--操作符 用成员函数实现 c1--; c1.printCom(); //c1.operator--() cout<<"hello..."<<endl; system("pause"); return ;}/*void operator<<(ostream &out, Complex &c1){ out<<"12345 生活真是苦"<<endl; out<<c1.a << " + " << c1.b << "i" << endl;}*/ostream& operator<<(ostream &out, Complex &c1){ out<<"12345 生活真是苦"<<endl; out<<c1.a << " + " << c1.b << "i" << endl; return out;}void main(){ int a = 10; Complex c1(1, 2), c2(3, 4); cout<<a<<endl; //按照数据类型 //1 cout << c1 ; //2 ostream 类中 添加 成员函数 .operator<< //ostream //cout.operator<<(c1); //2 函数返回值当左值 需要返回一个引用 cout << c1 << "aaddddd"; // //cout.operator<<(c1) .operator<<("aaddddd"); //void.operator<<("aaddddd"); system("pause");}
友元函数实现操作符重载的应用场景
1)友元函数和成员函数选择方法
- 当无法修改左操作数的类时,使用全局函数进行重载
- =, [], ()和->操作符只能通过成员函数进行重载
2)用友元函数 重载 << >>操作符
- istream 和 ostream 是 C++ 的预定义流类
- cin 是 istream 的对象,cout 是 ostream 的对象
- 运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
- 运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
- 用友员函数重载 << 和 >> ,输出和输入用户自定义的数据类型
a)用全局函数方法实现 << 操作符
ostream& operator<<(ostream &out, Complex &c1){ //out<<"12345,生活真是苦"<<endl; out<<c1.a<<" + "<<c1.b<<"i "<<endl; return out;}
//调用方法 cout<<c1;
//链式编程支持 cout<<c1<<"abcc";
//cout.operator<<(c1).operator<<("abcd");
/函数返回值充当左值 需要返回一个引用
b)类成员函数方法无法实现 << 操作符重载
- 因无法拿到cout这个类的源码
- cout.operator<<(c1);
友元函数重载操作符使用注意点
a) 友员函数重载运算符常用于运算符的左右操作数类型不同的情况
b)其他
- 在第一个参数需要隐式转换的情形下,使用友员函数重载运算符是正确的选择
- 友员函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
- C++中不能用友员函数重载的运算符有
= () [] ->
友元函数案例vector类
#include <iostream>using namespace std;//为vector类重载流插入运算符和提取运算符 class vector{ public : vector( int size =1 ) ; ~vector() ; int & operator[]( int i ) ; friend ostream & operator << ( ostream & output , vector & ) ; friend istream & operator >> ( istream & input, vector & ) ;private : int * v ; int len ;};vector::vector( int size ) { if (size <= 0 || size > 100 ) { cout << "The size of " << size << " is null !\n" ; abort() ; } v = new int[ size ] ; len = size ;}vector :: ~vector() { delete[] v ; len = 0 ; }int &vector::operator[]( int i ) { if( i >=0 && i < len ) return v[ i ] ; cout << "The subscript " << i << " is outside !\n" ; abort() ;}ostream & operator << ( ostream & output, vector & ary ){ for(int i = 0 ; i < ary.len ; i ++ ) output << ary[ i ] << " " ; output << endl ; return output ;}istream & operator >> ( istream & input, vector & ary ) { for( int i = 0 ; i < ary.len ; i ++ ) input >> ary[ i ] ; return input ;}void main(){ int k ; cout << "Input the length of vector A :\n" ; cin >> k ; vector A( k ) ; cout << "Input the elements of vector A :\n" ; cin >> A ; cout << "Output the elements of vector A :\n" ; cout << A ; system("pause");}
4.提高
1.运算符重载机制
编译器实现运算符重载实际上就是通过函数重载实现的,可分为全局函数方式,也可分为成员函数方式进行重载,并没有改变原操作符的属性和语义。只是针对某个特定类定义一种新的数据类型操作。
2.重载赋值运算符
- 赋值运算符重载用于对象数据的复制
- operator= 必须重载为成员函数
- 重载函数原型为:
类型 & 类名 :: operator= ( const 类名 & ) ;
结论:
1 先释放旧的内存
2 返回一个引用
3 =操作符 从右向左
#define _CRT_SECURE_NO_WARNINGS #include <iostream>using namespace std;//class Name{public: Name(const char *myp) { m_len = strlen(myp); m_p =(char *) malloc(m_len + 1); // strcpy(m_p, myp); } //Name obj2 = obj1; //解决方案: 手工的编写拷贝构造函数 使用深copy Name(const Name& obj1) { m_len = obj1.m_len; m_p = (char *)malloc(m_len + 1); strcpy(m_p, obj1.m_p); } //obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝 //obj3.operator=(obj1) Name& operator=(Name &obj1) { //先释放旧的内存 if (this->m_p != NULL) { delete[] m_p; m_len = 0; } //2 根据obj1分配内存大小 this->m_len = obj1.m_len; this->m_p = new char [m_len+1]; //把obj1赋值 strcpy(m_p, obj1.m_p); return *this; } ~Name() { if (m_p != NULL) { free(m_p); m_p = NULL; m_len = 0; } }protected:private: char *m_p ; int m_len; };//对象析构的时候 出现coredumpvoid objplaymain(){ Name obj1("abcdefg"); Name obj2 = obj1; //C++编译器提供的 默认的copy构造函数 浅拷贝 Name obj3("obj3"); obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝 //obj3.operator=(obj1) //operato=(Name &obj1) obj1 = obj2 = obj3; //obj2.operator=(obj3); //obj1 = void;}void main(){ objplaymain(); cout<<"hello..."<<endl; system("pause"); return ;}
3.重载下标运算符
- [ ]运算符用于访问数据对象的元素
- 重载格式
类型 类 :: operator[] ( 类型 ) ;
- 只能用成员函数重载,不能用友元函数重载
示例:
设 x 是类 X 的一个对象,则表达式
x [ y ]
可被解释为
x . operator [ ] ( y )
函数返回值当左值需要返回一个引用!
4.带下标和相等操作符的数组类
- 类的头文件
#ifndef NEWARRAY_H#define NEWARRAY_H#include <iostream>#include <stdlib.h>class NewArray{public: NewArray(); NewArray(int _len); NewArray(const NewArray & obj); ~NewArray(); void setData(int index,int var); int getData(int index); int length(); int& operator[](int i); NewArray& operator=(NewArray& obj); bool operator==(NewArray& obj); bool operator!=(NewArray& obj);private: int m_len; int *m_buf;};#endif // NEWARRAY_H
- 类的实现文件
#include "newarray.h"NewArray::NewArray(){ m_buf = NULL; m_len = -1;}NewArray::NewArray(int _len){ if(_len < 0) _len = 0; m_len = _len; m_buf = new int[m_len];}NewArray::NewArray(const NewArray & obj){ m_len = obj.m_len; m_buf = new int[m_len]; for(int i = 0;i < m_len;i++) { m_buf[i] = obj.m_buf[i]; }}NewArray::~NewArray(){ if(m_buf != NULL) { delete []m_buf; m_buf = NULL; m_len = -1; }}void NewArray::setData(int index,int var){ m_buf[index] = var;}int NewArray::getData(int index){ return m_buf[index];}int NewArray::length(){ return m_len;}int& NewArray::operator[](int i){ return m_buf[i];}NewArray& NewArray::operator=(NewArray& obj){ if(m_buf != NULL) { delete []m_buf; m_len = -1; m_buf = NULL; } m_len = obj.m_len; m_buf = new int[m_len]; for(int i = 0;i < m_len;i++) { m_buf[i] = obj.m_buf[i]; } return *this;}bool NewArray::operator==(NewArray& obj){ if(m_len != obj.m_len) { return false; } for(int i = 0;i < m_len;i++) { if(m_buf[i] != obj.m_buf[i]) { return false; } } return true;}bool NewArray::operator!=(NewArray& obj){ return !((*this) == obj);}
- 测试文件
#include "newarray.h"using namespace std;int main(){ NewArray a1(10); for (int i=0; i<a1.length(); i++) { //成员函数方式赋值 a1.setData(i, i); //下标运算符重载赋值 a1[i] = i; //函数返回值当左值,需要返回一个引用 //a1.operator [i] } cout<<"\na1: "; for (int i=0; i<a1.length(); i++) { //cout<<a1.getData(i)<<" ";//成员函数方式获取元素 //下标运算符方式获取数组元素 cout<<a1[i]<<"\t"; } cout<<endl; //赋值运算符重载 NewArray a2 = a1; cout<<"\na2: "; for (int i=0; i<a2.length(); i++) { cout<<a2.getData(i)<<" "; } cout<<endl; //3 NewArray a3(5); { a3 = a1; a3 = a2 = a1; cout<<"\na3: "; for (int i=0; i<a3.length(); i++) { cout<<a3[i]<<" "; } } //功能4 if (a3 == a1) { printf("\nequal\n"); } else { printf("\nnot equal\n"); } //a3.operator==(a1); //bool operator==(Array &a1); if (a3 != a1) { printf("\nnot equal\n"); } else { printf("\nequal\n"); } // //a3.operator!=(a1) // bool operator!=(Array &a1); cout<<"hello..."<<endl; return 1;}
5.重载函数调用运算符
- () 运算符用于函数调用
- 重载格式
类型 类 :: operator() ( 表达式表 ) ;
- 只能用成员函数重载,不能用友元函数重载
例1
设 x 是类 X 的一个对象,则表达式
x ( arg1, arg2, … )
可被解释为
x . operator () (arg1, arg2, … )
案例:
- 例:用重载()运算符实现数学函数的抽象
#include <iostream>class F { public : double operator ( ) ( double x , double y ) ; } ;double F :: operator ( ) ( double x , double y ) { return x * x + y * y ; }void main ( ) { F f ;f.getA(); cout << f ( 5.2 , 2.5 ) << endl ; // f . operator() (5.2, 2.5)}
- 例3 用重载()运算符实现 pk 成员函数
#include <iostream.h>class F { public : double memFun ( double x , double y ) ; } ;double F :: memFun ( double x , double y ) { return x * x + y * y ; }void main ( ) { F f ; cout << f.memFun ( 5.2 , 2.5 ) << endl ;}
6.不建议重载的运算符
理论知识:
1)&&和||是C++中非常特殊的操作符
2)&&和||内置实现了短路规则
3)操作符重载是靠函数重载来完成的
4)操作数作为函数参数传递
5)C++的函数参数都会被求值,无法实现短路规则
#include <cstdlib>#include <iostream>using namespace std;class Test{ int i;public: Test(int i) { this->i = i; } Test operator+ (const Test& obj) { Test ret(0); cout<<"执行+号重载函数"<<endl; ret.i = i + obj.i; return ret; } bool operator&& (const Test& obj) { cout<<"执行&&重载函数"<<endl; return i && obj.i; }};// && 从左向右void main(){ int a1 = 0; int a2 = 1; cout<<"注意:&&操作符的结合顺序是从左向右"<<endl; if( a1 && (a1 + a2) ) { cout<<"有一个是假,则不在执行下一个表达式的计算"<<endl; } Test t1 = 0; Test t2 = 1; //if( t1 && (t1 + t2) ) //t1 && t1.operator+(t2) // t1.operator&&( t1.operator+(t2) ) //1 && || 重载他们 不会产生短路效果 if( (t1 + t2) && t1) { //t1.operator+(t2) && t1; //(t1.operator+(t2)).operator&&(t1); cout<<"两个函数都被执行了,而且是先执行了+"<<endl; } //2 && 运算符的结合性 // 两个逻辑与运算符 在一块的时候, 采去谈 运算符的结合性 // 从左到右 (t1 + t2) && t1 ; 运算结果 && t2) //if( (t1 + t2) && t1 && t2) { //t1.operator+(t2) && t1; //(t1.operator+(t2)).operator&&(t1); cout<<"两个函数都被执行了,而且是先执行了+"<<endl; } system("pause"); return ;}
5.字符串类的实现
- 头文件
#ifndef MYSTRING_H#define MYSTRING_H#include <iostream>using namespace std;#include <stdlib.h>#include <string.h>class MyString{public: MyString(); MyString(int _len); MyString(const char *_str); MyString(const MyString & obj); ~MyString(); MyString& operator =(const MyString & obj); MyString& operator =(const char * _str); bool operator ==(const MyString & obj); bool operator ==(const char * _str); bool operator !=(const MyString & obj); bool operator !=(const char * _str); bool operator >(const MyString & obj); bool operator >(const char * _str); bool operator <(const MyString & obj); bool operator <(const char * _str); char& operator [](int index); friend ostream& operator<<(ostream & out,MyString & obj); friend istream& operator>>(istream & in,MyString & obj);private: int m_len; char *m_str;};#endif // MYSTRING_H
- 实现文件
#include "mystring.h"MyString::MyString(){ m_len = 0; m_str = NULL;}MyString::MyString(int _len){ if(_len < 0) _len = 0; m_len = _len; m_str = new char[m_len+1]; memset(m_str,0,m_len);}MyString::MyString(const char *_str){ if(_str == NULL) { m_len = 0; m_str = new char[m_len+1]; strcpy(m_str,""); }else { m_len = strlen(_str); m_str = new char[m_len+1]; strcpy(m_str,_str); }}MyString::MyString(const MyString & obj){ m_len = obj.m_len; m_str = new char[m_len+1]; strcpy(m_str,obj.m_str);}MyString::~MyString(){ if(m_str != NULL) { delete []m_str; m_str = NULL; m_len = 0; }}MyString& MyString::operator =(const MyString & obj){ if(m_str != NULL) { delete []m_str; m_str = NULL; m_len = 0; } m_len = obj.m_len; m_str = new char[m_len+1]; strcpy(m_str,obj.m_str); return *this;}MyString& MyString::operator =(const char * _str){ if(m_str != NULL) { delete []m_str; m_str = NULL; m_len = 0; } if(_str == NULL) { m_len = 0; m_str = new char[m_len+1]; strcpy(m_str,""); }else { m_len = strlen(_str); m_str = new char[m_len+1]; strcpy(m_str,_str); } return *this;}bool MyString::operator ==(const MyString & obj){ if(m_len != obj.m_len) { return false; } return !strcmp(m_str,obj.m_str);}bool MyString::operator ==(const char * _str){ if(_str == NULL) { if(m_len == 0) { return true; }else{ return false; } }else{ if(m_len == strlen(_str)){ return !strcmp(m_str,_str); }else{ return false; } }}bool MyString::operator !=(const MyString & obj){ return !((*this) == obj);}bool MyString::operator !=(const char * _str){ return !((*this) == _str);}bool MyString::operator >(const MyString & obj){ if(strcmp(m_str,obj.m_str) > 0) { return true; }else{ return false; }}bool MyString::operator >(const char * _str){ if(strcmp(m_str,_str) > 0) { return true; }else{ return false; }}bool MyString::operator <(const MyString & obj){ if(strcmp(m_str,obj.m_str) < 0) { return true; }else{ return false; }}bool MyString::operator <(const char * _str){ if(strcmp(m_str,_str) < 0) { return true; }else{ return false; }}char& MyString::operator [](int index){ return m_str[index];}ostream& operator<<(ostream & out,MyString & obj){ out<<obj.m_str; return out;}istream& operator>>(istream & in,MyString & obj){ in>>obj.m_str; return in;}
- 测试文件
#define _CRT_SECURE_NO_WARNINGS#include "mystring.h"void main01(){ MyString s1; MyString s2("s2"); MyString s2_2 = NULL; MyString s3 = s2; MyString s4 = "s4444444444"; //测试运算符重载 和 重载[] //= s4 = s2; s4 = "s2222"; s4[1] = '4'; printf("%c", s4[1]); cout<<s4 <<endl; //ostream& operator<<(ostream &out, MyString &s) //char& operator[] (int index) //MyString& operator=(const char *p); //MyString& operator=(const MyString &s); cout<<"hello..."<<endl; system("pause"); return ;}void main02(){ MyString s1; MyString s2("s2"); MyString s3 = s2; if (s2 == "aa") { printf("相等"); } else { printf("不相等"); } if (s3 == s2) { printf("相等"); } else { printf("不相等"); }}void main03(){ MyString s1; MyString s2("s2"); MyString s3 = s2; s3 = "aaa"; if (s3 < "bbbb" ) { printf("s3 小于 bbbb"); } else { printf("s3 大于 bbbb"); } MyString s4 = "aaaaffff"; //strcpy(s4.c_str(), "aa111"); //MFC cout<<s4<<endl;}void main011(){ MyString s1(128); cout<<"\n请输入字符串(回车结束)"; cin>>s1; cout<<s1; system("pause");}int main(){ MyString s1(128); cout<<"\n请输入字符串(回车结束)"; cin>>s1; cout<<s1<<endl; system("pause"); return 0;}
总结
- 操作符重载是C++的强大特性之一
- 操作符重载的本质是通过函数扩展操作符的语义
- operator关键字是操作符重载的关键
- friend关键字可以对函数或类开发访问权限
- 操作符重载遵循函数重载的规则
- 操作符重载可以直接使用类的成员函数实现
- =, [], ()和->操作符只能通过成员函数进行重载
- ++操作符通过一个int参数进行前置与后置的重载
- C++中不要重载&&和||操作符
附录:运算符和结合性
- 16运算符重载
- 运算符重载 [++,--,+,<<; &&,||(不可重载)]
- 重载之运算符重载
- 16 oj 复数类 重载运算符+
- 16 oj 矩阵求和 重载运算符
- 重载赋值运算符
- C++运算符重载
- 运算符重载
- 运算符重载总结
- 运算符重载例子
- 运算符重载
- 运算符重载
- 基础:运算符重载
- 运算符重载
- 运算符重载
- 重载赋值运算符
- C#运算符重载
- C++-运算符重载
- js中将数字格式的日期化为yyyy-MM-dd样式
- C/C++ "#"与"##"的作用与应用
- 2017linux面试题整理
- nginx中修改server_name无效,修改为www.test.com无法访问,通过localhost可以访问
- jvm:gc算法——复制、标记清除
- 16运算符重载
- RecycleView冲突这点事儿!
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
- ASSERT(断言)的作用
- Hello,占坑
- Android MVP模式简单例子实战
- 趣店前端实习面试总结
- Android小红点儿数量提示
- hibernateTemplate 与session的区别 HibernateTemplate、HibernateDaoSupport两种方法实现增删改查