玩轉C++運算符重載
運算符重載語法:返回值類型 operator運算符(參數列表) { 代碼邏輯。。。 }
C++中的運算符重載是通過函數來實現的,可以將重載的運算符看作是類成的一個成員函數,向普通函數一樣調用。如重載String類的 + 運算符,調用的時候可以這樣:
class {
// .....
String operator+(const String &str)
{ .... }
}
String str1 = "hello ";
String str2 = "cplusplus";
String str3 = str1.operator+(str2); 從上述代碼中可以看出,operator+就像是String類的一個函數,可以像普通函數一樣調用,將要相加的字符串對象作為實參傳遞給函數即可。所以從這可以得出一個函數重載的步聚:(以上述+重載為例)
1、寫出運算符的函數原型
str1.operator+(str2);
從這可以得知,+ 需要兩個操作數,str1和str2(即兩個字符串對象),返回值類型為String對象(加法運算後的結果)。由於是作為類的成員函數重載,所以str1在進行 + 運算時作為this指針傳給函數,函數隻需要一個參數即可,即被相加的字符串對象str2。
2、寫出函數聲明
從函數原型可以得出函數聲明:String operator+(const String &str);
3、實現函數細節
String String::operator+(const String &str)
{
if (str.buff == nullptr)
{
return *this;
}
size_t totallen = str.len + this->len + 1;
char *buff = new char[totallen];
strcpy(buff, this->buff);
strcat(buff, str.buff);
String temp(buff);
return temp;
}
下麵這個示例重載了字符串操作的常用操作符:
//
// String.h
// C++運算符重載
//
// Created by 楊信 on 14-5-8.
// Copyright (c) 2014年 yangxin. All rights reserved.
//
#ifndef __C______String__
#define __C______String__
#include <iostream>
using namespace std;
class String
{
private:
char *buff;
size_t len;
public:
String();
// 用一個字符串初始化對象
String(const char *buff);
// 拷貝構造
String(const String &str);
// 析構
~String();
// 設置字符串內容
void setString(const char *buff);
// 獲取字符串的長度
size_t length() const;
// 獲取字符串內容
char * getStr() const;
// 比較兩個字符串是否相等
bool operator==(String &str);
// 比較兩個字符串是否不相等
bool operator!=(String &str);
// 比較兩個字符串的大小
bool operator>(String &str);
// 比較兩個字符串的大小
bool operator<(String &str);
// 獲取或修改字符串中的某一個字符
char& operator[](int index);
// 賦值構造函數
String& operator=(const String &str);
// 兩個字符串相加
String operator+(const String &str);
// 字符串累加
String& operator+=(const String &str);
// 從輸入流中獲取字符串
friend istream& operator>>(istream &input, String &str);
// 將字符串輸出到輸出流
friend ostream& operator<<(ostream &output, const String &str);
};
#endif /* defined(__C______String__) */
//
// String.cpp
// C++運算符重載
//
// Created by 楊信 on 14-5-8.
// Copyright (c) 2014年 yangxin. All rights reserved.
//
#include "String.h"
#include <string>
#include <cassert>
#include <cmath>
String::String()
{
this->buff = nullptr;
this->len = 0;
}
// 用一個字符串初始化對象
String::String(const char *buff):buff(nullptr), len(0)
{
setString(buff);
}
// 拷貝構造
String::String(const String &str)
{
setString(str.buff);
}
// 析構
String::~String()
{
// 釋放內存
if (this->buff != nullptr)
{
delete[] buff;
buff = nullptr;
len = 0;
}
}
void String::setString(const char *buff)
{
if (buff == nullptr)
{
return;
}
if (this->buff != nullptr) {
delete[] this->buff;
this->buff = nullptr;
this->len = 0;
}
size_t len = strlen(buff);
this->buff = new char[len + 1];
this->len = len;
strcpy(this->buff, buff);
}
// 獲取字符串的長度
size_t String::length() const
{
return this->len;
}
// 獲取字符串內容
char * String::getStr() const
{
return this->buff;
}
// 獲取或修改字符串中的某一個字符
char& String::operator[](int index)
{
assert(index < this->len);
return this->buff[index];
}
// 比較兩個字符串是否相等
bool String::operator==(String &str)
{
if (this->len != str.len)
{
return false;
}
for (int i = 0; i < this->len; ++i)
{
if (this->buff[i] != str[i])
{
return false;
}
}
return true;
}
// 比較兩個字符串是否不相等
bool String::operator!=(String &str)
{
return !(*this == str);
}
// 比較兩個字符串的大小
bool String::operator>(String &str)
{
char *pstr = this->buff;
char *pstr2 = str.buff;
while (*pstr != '\0' && *pstr2 != '\0')
{
if (*pstr > *pstr2) {
return true;
}
pstr++;
pstr2++;
}
return false;
}
// 比較兩個字符串的大小
bool String::operator<(String &str)
{
return !(*this > str);
}
// 賦值構造函數
String& String::operator=(const String &str)
{
setString(str.buff);
return *this;
}
// 兩個字符串相加
String String::operator+(const String &str)
{
if (str.buff == nullptr)
{
return *this;
}
size_t totallen = str.len + this->len + 1;
char *buff = new char[totallen];
strcpy(buff, this->buff);
strcat(buff, str.buff);
String temp(buff);
return temp;
}
// 字符串累加
String& String::operator+=(const String &str)
{
if (str.buff == nullptr)
{
return *this;
}
// 創建一個臨時緩衝區,存儲對象本身的字符串和相加的字符串
size_t len = this->len + str.length();
char *temp = new char[len + 1];
strcpy(temp, this->buff);
strcat(temp, str.buff);
// 設置新的字符串給對象本身
setString(temp);
return *this;
}
// 從輸入流中獲取字符串
istream& operator>>(istream &input, String &str)
{
// 在堆區創建臨時緩衝區,接收用戶輸入
int size = 1024 * 10;
char *tempbuff = new char[size];
memset(tempbuff, 0, size);
// 獲取用戶輸入
input.getline(tempbuff, size);
// 將臨時緩衝中的字符串保存到str對象的字符串緩衝區中
str.setString(tempbuff);
// 釋放臨時緩衝區數據
delete[] tempbuff;
tempbuff = nullptr;
return input;
}
// 將字符串輸出到輸出流
ostream& operator<<(ostream &output, const String &str)
{
output << str.getStr();
return output;
}
// 測試用例
//
// main.cpp
// String(運算符重載)
//
// Created by 楊信 on 14-5-8.
// Copyright (c) 2014年 yangxin. All rights reserved.
//
#include <iostream>
#include "String.h"
#include <cmath>
using namespace std;
int main(int argc, const char * argv[])
{
// 初始化
String str1("helloz");
String str2("helloz");
// 獲取字符中內容
cout << str1.getStr() << endl;
// 獲取字符串的長度
cout << "長度:" << str1.length() << endl;
// 獲取第字符串中的第一個字符
cout << "第1個字符:" << str1[0] << endl;
// 比較兩個字符串是否相等,相等返回1,否則返回0
bool isequal = str1 == str2;
cout << isequal << endl;
// 比較兩個字符串的大小,str1大於str2返回1,否則返回0
cout << (str1 > str2) << endl;
// 修改字符串中的第2個字符為C
String s = "Hello";
s[1] = 'C';
cout << s << endl;
// 測試用一個字符串去初始化另外一個字符串
String str3 = str2;
cout << str3.getStr() << endl;
String str4;
str4 = str3;
cout << str4.getStr() << endl;
// 測試兩個字符串相加
String str5 = str1 + str2;
cout << &str5 << endl;
cout << str5.getStr() << endl;
// 測試字符串連等
String str6;
String str7 = str6 = str5;
cout << str6.getStr() << " | " << str7.getStr() << endl;
// 測試字符串累加
String str8 = "i love c++ ";
str8 += "i love c ";
cout << str8.getStr() << endl;
// 從輸入流讀取字符串
String str9;
cout << "Please a string:";
cin >> str9;
// 將字符串輸出到輸出流
cout << str9 << endl;
return 0;
}
運算符重載注意事項:
- 友元函數重載運算符時需要傳遞所有操作數
- 成員函數重載,會將操作數本身做為this指針作為參數傳入函數,如果是多元操作符,隻需與它被操作的數傳入函數即可
-
= 號重載時,如果對象中有新分配內存的成員,要先delete,再new,如果要支持連等操作,需要返回對象本身的引用
-
函數返回值作左值時,返回值必須為引用
- 隻有C++預定義的操作符集中的操作符才可以被重載(不能自己隨便寫一個操作符,如:+-)
- 重載操作符不能改變操作符的優先級,例如:先乘徐,後加減
- 重載操作符不能改變操作數的個數
以下幾種運算符不能被重載:
- . :成員選擇運算符
- :: :作用域運算符
- * : 指針運算符
- # :預處理標誌
- ?: :三目運算符,沒有確定性,重載沒有意義
最後更新:2017-04-03 12:56:35
上一篇:
Netty4詳解二:開發第一個Netty應用程序
下一篇:
如何解決每次打開office2007、2010、2013都會出現正在配置
網絡攻擊更難預料,IoT到底是福是禍?
智慧汽車價值何在?車聯網和無人車的中間形態
Ubuntu 12.10打破PC與網絡藩籬 整合雲端應用
成都雲棲大會,阿裏1582.73億營收背後的持續交付如何玩?
數據結構之AVL樹
Android開發7——android.database.CursorIndexOutOfBoundsException:Index -1 requested, with a size of 1
機房收費係統之周結賬單
6月30日雲棲精選夜讀:程序員技術與文藝的PK,來首屆阿裏巴巴研發效能嘉年華
HttpWebRequest的GetRespons偶爾超時、死掉的原因及解決辦法
從機器學習談起