运算符重载
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;
}
};
Complex myAdd(Complex &c1, Complex &c2)
{
Complex tmp(c1.a + c2.a, c1.b+ c2.b);
return tmp;
}
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;
Complex c1(1, 2), c2(3, 4);
Complex c3;
Complex c4 = c1 + c2;
c4.printCom();
cout<<"hello..."<<endl;
return 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
2.限制
3.基础
例如:
//全局函数 完成 +操作符 重载
Complex operator+(Complex &c1, Complex &c2)
//类成员函数 完成 -操作符 重载
Complex operator-(Complex &c2)
例如1:通过类成员函数完成-操作符重载
Complex c4 = c1 - c2;
c4.printCom();
例如2:通过全局函数方法完成+操作符重载
int main()
{
Complex c1(1, 2), c2(3, 4);
Complex c3 = c1 + c2;
c3.printCom();
}
例如3
++
++
. ++
. ++
//调用方法
++c1 ; //=需要写出操作符重载函数原形
c1.printCom();
//运算符重载函数名定义
//首先承认操作符重载是一个函数 定义函数名operator++
//分析函数参数 根据左右操作数的个数,operator++(Complex &c1)
//分析函数返回值Complex& operator++(Complex &c1)
返回它自身
例如4
Complex& operator--()
{
this->a--;
this->b--;
return *this;
}
//4.2调用方法
--c1;
c1.printCom();
//4.3前置—运算符重载函数名定义
//c1.operator–()
例如5
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
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)
{
Complex tmp = c1;
c1.a ++;
c1.b ++;
return tmp;
}
void main()
{
Complex c1(1, 2), c2(3, 4);
Complex c3 = c1 + c2;
c3.printCom();
Complex c4 = c1 - c2;
c4.printCom();
++c1;
c1.printCom();
--c1;
c1.printCom();
c1++;
c1.printCom();
c1--;
c1.printCom();
cout<<"hello..."<<endl;
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
定义运算符重载函数名的步骤
全局函数、类成员函数方法实现运算符重载步骤
1)要承认操作符重载是一个函数,写出函数名称operator+ ()
2)根据操作数,写出函数参数
3)根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务
运算符重载的正规写法
#include <iostream>
using namespace std;
class Complex
{
private:
int a;
int b;
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)
{
Complex tmp = *this;
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);
Complex c3 = c1 + c2;
c3.printCom();
Complex c4 = c1 - c2;
c4.printCom();
++c1;
c1.printCom();
--c1;
c1.printCom();
c1++;
c1.printCom();
c1--;
c1.printCom();
cout<<"hello..."<<endl;
system("pause");
return ;
}
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;
cout << c1 ;
cout << c1 << "aaddddd";
system("pause");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
友元函数实现操作符重载的应用场景
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;
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");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
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(const Name& obj1)
{
m_len = obj1.m_len;
m_p = (char *)malloc(m_len + 1);
strcpy(m_p, obj1.m_p);
}
Name& operator=(Name &obj1)
{
if (this->m_p != NULL)
{
delete[] m_p;
m_len = 0;
}
this->m_len = obj1.m_len;
this->m_p = new char [m_len+1];
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;
};
void objplaymain()
{
Name obj1("abcdefg");
Name obj2 = obj1;
Name obj3("obj3");
obj3 = obj1;
obj1 = obj2 = obj3;
}
void main()
{
objplaymain();
cout<<"hello..."<<endl;
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
#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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
#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;
}
cout<<"\na1: ";
for (int i=0; i<a1.length(); 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;
NewArray a3(5);
{
a3 = a1;
a3 = a2 = a1;
cout<<"\na3: ";
for (int i=0; i<a3.length(); i++)
{
cout<<a3[i]<<" ";
}
}
if (a3 == a1)
{
printf("\nequal\n");
}
else
{
printf("\nnot equal\n");
}
if (a3 != a1)
{
printf("\nnot equal\n");
}
else
{
printf("\nequal\n");
}
cout<<"hello..."<<endl;
return 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
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 ;
}
#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 + t2) && t1)
{
cout<<"两个函数都被执行了,而且是先执行了+"<<endl;
}
{
cout<<"两个函数都被执行了,而且是先执行了+"<<endl;
}
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
#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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
#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;
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";
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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
总结
- 操作符重载是C++的强大特性之一
- 操作符重载的本质是通过函数扩展操作符的语义
- operator关键字是操作符重载的关键
- friend关键字可以对函数或类开发访问权限
- 操作符重载遵循函数重载的规则
- 操作符重载可以直接使用类的成员函数实现
- =, [], ()和->操作符只能通过成员函数进行重载
- ++操作符通过一个int参数进行前置与后置的重载
- C++中不要重载&&和||操作符
附录:运算符和结合性
友元函数