運算符重載
- 運算符重載
- 概念
- 限制
- 基礎
- 提高
- 字元串類的實作
- 附錄運算符和結合性
本人部落格收集自網上前人資料,隻為做筆記複習,而且好的東西應該和大家分享才是!如有冒犯,告知鄙人定會删除
1.概念
- 什麼是運算符重載

所謂重載,就是重新賦予新的含義。函數重載就是對一個已有的函數賦予新的含義,使之實作新功能,是以,一個函數名就可以用來代表不同功能的函數,也就是”一名多用”。
運算符也可以重載。實際上,我們已經在不知不覺之中使用了運算符重載。例如,大 家都已習慣于用加法運算符”+”對整數、單精度數和雙精度數進行加法運算,如5+8, 5.8 +3.67等,其實計算機對整數、單精度數和雙精度數的加法操作過程是很不相同的, 但由于C++已經對運算符”+”進行了重載,是以就能适用于int, float, doUble類型的運算。
又如”<<“是C++的位運算中的位移運算符(左移),但在輸出操作中又是與流對 象cout 配合使用的流插入運算符,”>>“也是位移運算符(右移),但在輸入操作中又是與流對象 cin 配合使用的流提取運算符。這就是運算符重載(operator overloading)。C++系統對”<<“和”>>“進行了重載,使用者在不同的場合下使用它們時,作用是不同 的。對”<<“和”>>“的重載處理是放在頭檔案stream中的。是以,如果要在程式中用”<< “和”>>”作流插入運算符和流提取運算符,必須在本檔案子產品中包含頭檔案stream(當然還應當包括”using namespace std“)。
現在要讨論的問題是:使用者能否根據自己的需要對C++已提供的運算符進行重載,賦予它們新的含義,使之一名多用。?
- 運算符重載入門技術推演
-
為什麼會用運算符重載機制
用複數類舉例
原因 Complex是使用者自定義類型,編譯器根本不知道如何進行加減.是以編譯器給提供了一種機制,讓使用者自己去完成,自定義類型的加減操作。這個機制就是運算符重載機制Complex c3 = c1 + c2;
- 運算符重載的本質是一個函數
-
#include <iostream>
using namespace std;
class Complex
{
public:
int a;
int b;
public:
Complex(int a=, int b=)
{
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 = , b = ;
int c;
c = a + b; //1 基礎資料類型 編譯器已經知道了. 如何運算
// a + bi 複數運算規則
Complex c1(, ), c2(, );
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 ;
}
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(, ), c2(, );
//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=, int b=)
{
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(, ), c2(, );
//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=, int b=)
{
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(, ), c2(, );
//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 = ;
Complex c1(, ), c2(, );
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 = ) ;
~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 <= || size > )
{
cout << "The size of " << size << " is null !\n" ; abort() ;
}
v = new int[ size ] ; len = size ;
}
vector :: ~vector()
{
delete[] v ;
len = ;
}
int &vector::operator[]( int i )
{
if( i >= && i < len ) return v[ i ] ;
cout << "The subscript " << i << " is outside !\n" ; abort() ;
}
ostream & operator << ( ostream & output, vector & ary )
{
for(int i = ; i < ary.len ; i ++ )
output << ary[ i ] << " " ;
output << endl ;
return output ;
}
istream & operator >> ( istream & input, vector & ary )
{
for( int i = ; 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 + ); //
strcpy(m_p, myp);
}
//Name obj2 = obj1;
//解決方案: 手工的編寫拷貝構造函數 使用深copy
Name(const Name& obj1)
{
m_len = obj1.m_len;
m_p = (char *)malloc(m_len + );
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 = ;
}
//2 根據obj1配置設定記憶體大小
this->m_len = obj1.m_len;
this->m_p = new char [m_len+];
//把obj1指派
strcpy(m_p, obj1.m_p);
return *this;
}
~Name()
{
if (m_p != NULL)
{
free(m_p);
m_p = NULL;
m_len = ;
}
}
protected:
private:
char *m_p ;
int m_len;
};
//對象析構的時候 出現coredump
void 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 = -;
}
NewArray::NewArray(int _len)
{
if(_len < )
_len = ;
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 = ;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 = -;
}
}
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 = -;
m_buf = NULL;
}
m_len = obj.m_len;
m_buf = new int[m_len];
for(int i = ;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 = ;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();
for (int i=; i<a1.length(); i++)
{
//成員函數方式指派
a1.setData(i, i);
//下标運算符重載指派
a1[i] = i;
//函數傳回值當左值,需要傳回一個引用
//a1.operator [i]
}
cout<<"\na1: ";
for (int i=; i<a1.length(); i++)
{
//cout<<a1.getData(i)<<" ";//成員函數方式擷取元素
//下标運算符方式擷取數組元素
cout<<a1[i]<<"\t";
}
cout<<endl;
//指派運算符重載
NewArray a2 = a1;
cout<<"\na2: ";
for (int i=; i<a2.length(); i++)
{
cout<<a2.getData(i)<<" ";
}
cout<<endl;
//3
NewArray a3();
{
a3 = a1;
a3 = a2 = a1;
cout<<"\na3: ";
for (int i=; 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 ;
}
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 ( , ) << 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 ( , ) << 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();
cout<<"執行+号重載函數"<<endl;
ret.i = i + obj.i;
return ret;
}
bool operator&& (const Test& obj)
{
cout<<"執行&&重載函數"<<endl;
return i && obj.i;
}
};
// && 從左向右
void main()
{
int a1 = ;
int a2 = ;
cout<<"注意:&&操作符的結合順序是從左向右"<<endl;
if( a1 && (a1 + a2) )
{
cout<<"有一個是假,則不在執行下一個表達式的計算"<<endl;
}
Test t1 = ;
Test t2 = ;
//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 = ;
m_str = NULL;
}
MyString::MyString(int _len)
{
if(_len < )
_len = ;
m_len = _len;
m_str = new char[m_len+];
memset(m_str,,m_len);
}
MyString::MyString(const char *_str)
{
if(_str == NULL)
{
m_len = ;
m_str = new char[m_len+];
strcpy(m_str,"");
}else
{
m_len = strlen(_str);
m_str = new char[m_len+];
strcpy(m_str,_str);
}
}
MyString::MyString(const MyString & obj)
{
m_len = obj.m_len;
m_str = new char[m_len+];
strcpy(m_str,obj.m_str);
}
MyString::~MyString()
{
if(m_str != NULL)
{
delete []m_str;
m_str = NULL;
m_len = ;
}
}
MyString& MyString::operator =(const MyString & obj)
{
if(m_str != NULL)
{
delete []m_str;
m_str = NULL;
m_len = ;
}
m_len = obj.m_len;
m_str = new char[m_len+];
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 = ;
}
if(_str == NULL)
{
m_len = ;
m_str = new char[m_len+];
strcpy(m_str,"");
}else
{
m_len = strlen(_str);
m_str = new char[m_len+];
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 == )
{
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) > )
{
return true;
}else{
return false;
}
}
bool MyString::operator >(const char * _str)
{
if(strcmp(m_str,_str) > )
{
return true;
}else{
return false;
}
}
bool MyString::operator <(const MyString & obj)
{
if(strcmp(m_str,obj.m_str) < )
{
return true;
}else{
return false;
}
}
bool MyString::operator <(const char * _str)
{
if(strcmp(m_str,_str) < )
{
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[] = '4';
printf("%c", s4[]);
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();
cout<<"\n請輸入字元串(回車結束)";
cin>>s1;
cout<<s1;
system("pause");
}
int main()
{
MyString s1();
cout<<"\n請輸入字元串(回車結束)";
cin>>s1;
cout<<s1<<endl;
system("pause");
return ;
}
總結
- 操作符重載是C++的強大特性之一
- 操作符重載的本質是通過函數擴充操作符的語義
- operator關鍵字是操作符重載的關鍵
- friend關鍵字可以對函數或類開發通路權限
- 操作符重載遵循函數重載的規則
- 操作符重載可以直接使用類的成員函數實作
- =, [], ()和->操作符隻能通過成員函數進行重載
- ++操作符通過一個int參數進行前置與後置的重載
- C++中不要重載&&和||操作符