本片博客是作者在學習c++的過程中的筆記記錄,希望和各位讀者一起學習交流
文章目錄
運算符重載
- 概念
運算符重載,就是對已有的運算符重新進行定義,賦予其另一種功能,以適應不同的數據類型 - 基礎
- 運算符函數是一種特殊的成員函數或者友元函數
- 成員函數的語法形式:
類型 類名::operator op(參數表)
{
//操作
} - 一個運算符被重載後,原有的意義沒有失去,只是定義了相對特定類的一個新運算符
- 例如:
- //全局函數 完成 + 操作符 重載
Complex operator+(Complex &c1,Complex &c2); - //類成員函數 完成 - 操作符 重載
Complex operator-(Compelx &c2);
- //全局函數 完成 + 操作符 重載
- 本質
運算符重載的本質是函數調用 - 用成員函數或友元函數重載運算符
- 二元運算符
ObjectL op ObjectR
重載爲成員函數,解釋爲:
ObjectL.operator op(ObjectR)
左操作數由ObjectL通過this指針傳遞,右操作數由參數ObjectR傳遞
重載爲友元函數,解釋爲:
operator op(ObjectL,ObjectR)
左右操作數都由參數傳遞 - 一元運算符
Object op 或 op Object
重載爲成員函數,解釋爲:
Object.operator op()
操作數由對象Object通過this指針隱含傳遞
重載爲友元函數,解釋爲:
operator op(Object)
操作數由參數表Object提供
eg:重載前置++、後置++運算符- 重載前置++:
成員函數的重載: 函數類型& operator++()
友元函數的重載:friend 函數類型& operator++(類型& ) - 後置++運算符的重載方式:
成員函數的重載:函數類型 operator++(int)
友元函數的重載:friend 函數類型 operator++(類型&, int)
- 重載前置++:
- 二元運算符
注意:重載後置++的返回的是右值,因此返回類型不能加引用
上述程序是重載後置++而且是返回對象的引用,會引用程序宕機,因爲tmp是一個臨時變量,當後置++運算結束後,tmp就會消失,因此必須返回一個對象,也即會返回一個匿名對象。
-
利用友元函數重載輸入、輸出流(函數返回值充當左值,需要返回一個引用)
- 基礎知識:
- istream和ostream是c++預定義流類
- cin是istream的對象,cout是ostream的對象
- 運算符<<由ostream重載爲插入操作,用於輸出基本類型數據
- 運算符>>由istream重載爲提取操作符,用於輸入基本類型數據
- 輸出流
函數原型:
friend ostream & operator<<(ostream &out,Test &test)
函數定義:
ostream & operator<<(ostream &out,Test &test)
{
out << test.a << endl;
return out;
} - 輸入流
函數原型:
friend istream & operator>>(istream &in,Test &test)
函數定義:
istream & operator>>(istream &in,Test &test)
{
in>>test.a;
return in;
} - c++中不能用友元函數重載的運算符:=、()、[]、->
- 基礎知識:
-
重載操作符“=”解決賦值淺拷貝問題
要點:- 先釋放內存
- 返回一個引用
- =操作符,結合順序是從右向左
-
重載運算符[]
函數原型:
int & operator[](int i);
類型 類::operator[](類型); -
重載運算符()
函數原型:
double operator()(double x,double y);
類型 類::operator()(表達式); -
&&、||運算符
這兩個運算符不進行重載,因爲運算符重載是經過函數調用,但是不可以實現&&、||本身的短路原則 -
重載string案例(案例來自於C++ Primer Plus 第6版 P442)
string.h#pragma once #include<iostream> using std::ostream; using std::istream; class MyString { private: char *str; int len; public: static const int CINLIM = 80; MyString(const char *); MyString(); MyString(const MyString &); ~MyString(); MyString & operator=(const MyString ); MyString & operator=(const char *); char & operator[](int i); const char & operator[](int i) const; friend bool operator<(const MyString &st1, const MyString &st2); friend bool operator>(const MyString &st1, const MyString &st2); friend bool operator==(const MyString &st1, const MyString &st2); friend ostream & operator<<(ostream & os, const MyString &st); friend istream & operator>>(istream & is, const MyString &st); };
string.cpp
#define _CRT_SECURE_NO_WARNINGS #include "string.h" #include<cstring> using std::cin; using std::cout; MyString::MyString(const char * s) { len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); } MyString::MyString() { len = 4; str = new char[1]; str[0] = '\0'; } MyString::MyString(const MyString & st) { len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); } MyString::~MyString() { delete[]str; } MyString & MyString::operator=(const MyString st) { if (this == &st) return *this; delete[]str; len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); return *this; } MyString & MyString::operator=(const char *s) { delete[]str; len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); return *this; } char & MyString::operator[](int i) { return str[i]; } const char & MyString::operator[](int i) const { return str[i]; } bool operator<(const MyString & st1, const MyString & st2) { return (std::strcmp(st1.str, st2.str) < 0); } bool operator>(const MyString & st1, const MyString & st2) { return st1 < st2; } bool operator==(const MyString & st1, const MyString & st2) { return (std::strcmp(st1.str, st2.str) == 0);; } ostream & operator<<(ostream & os, const MyString & st) { os << st.str; return os; } istream & operator >> (istream & is, MyString & st) { char temp[MyString::CINLIM]; is.get(temp, MyString::CINLIM); if (is) st = temp; while (is && is.get() != '\n') continue; return is; }