C++基础11-类和对象之操作符重载1
總結:
1、運算符重載的本質是函數重載
2、運算符重載可分為成員函數重載和全局函數重載(差一個參數)
3、運算符重載函數的參數至少有一個是類對象(或類對象的引用)
4、不可以被重載的操作符有:成員選擇符(.) 成員對象選擇符(.*)?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?域解析操作符(::) 條件操作符(?:)
5、前置加加 可以連續使用 后置加加 不可以連續使用
6、前置加加(減減)的運算符重載和普通運算符重載一樣,后置加加(減減)的運算符重載需要加一個占位符
7、輸入輸出運算符重載定義為全局函數重載。因為成員函數重載會發生歧義
8、輸入輸出運算符重載借助輸入輸出流(ostream istream)
9、雙目運算符就是有兩個參數(+,-),單目運算符有一個參數(++,--)
10、重載的前置加加 Complex& operator++(Complex &c1) ?//返回引用的目的是使用連續前置加加
? ? ? ?重載的后置加加 const Complex& operator++(Complex &c1, int)?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //加const的原因是后置加加不能連續使用
11、右移操作符重載:friend ostream& operator<<(ostream &os, Complex &c);
?? ??? ??? ??? ??? ?ostream& operator<<(ostream &os) ?//c1.operator<<(cout)
?? ??? ??? ??? ??? ?{?
?? ??? ??? ??? ??? ??? ?os << "(" << this->a << "," << this->b << "i)";
?? ??? ??? ??? ??? ??? ?return os;
?? ??? ??? ??? ??? ?}
? ? ?左移操作符重載:friend istream& operator>>(istream &is, Complex &c);
?? ??? ??? ??? ??? ?istream& operator>>(istream &is, Complex &c)
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?cout << "a:";
?? ??? ??? ??? ??? ??? ?is >> c.a;
?? ??? ??? ??? ??? ??? ?cout << "b:";
?? ??? ??? ??? ??? ??? ?is >> c.b;
?? ??? ??? ??? ??? ??? ?return is;
?? ??? ??? ??? ??? ?}
12、若某函數中類想引用私有成員,則將此函數在這個類中聲明為友元函數
13、除了賦值號(=)外,基類中被重載的操作符都將被派生類繼承
1、操作符重載格式
重載函數的一般格式如下:
函數類型 operator 運算符名稱(形參表列) {
? ? ? ? ?重載實體;
}
operator 運算符名稱 在一起構成了新的函數名。比如
const Complex operator+(const Complex &c1,const Complex &c2);
我們會說,operator+ 重載了重載了運算符+。
2、重載規則
?
4.10.2 重載規則
(1)C++不允許用戶自己定義新的運算符,只能對已有的 C++運算符進行重載。
例如,有人覺得 BASIC 中用“* *”作為冪運算符很方便,也想在 C++中將“**”定義為冪運算符,用“3**5”表示 35,這是不行的。
(2)C++允許重載的運算符
C++中絕大部分運算符都是可以被重載的。
不能重載的運算符只有 4 個:成員選擇符(.) 成員對象選擇符(.*)???域解析操作符(::) 條件操作符(?:)
前兩個運算符不能重載是為了保證訪問成員的功能不能被改變,域運算符合sizeof 運算符的運算對象是類型而不是變量或一般表達式,不具備重載的特征。
?
3)重載不能改變運算符運算對象(即操作數)的個數。
如,關系運算符“>”和“<”等是雙目運算符,重載后仍為雙目運算符,需要兩 個參數。運算符”+“,”-“,”*“,”&“等既可以作為單目運算符,也可以作為雙 目運算符,可以分別將它們重載為單目運算符或雙目運算符。
4)重載不能改變運算符的優先級別。
例如”*“和”/“優先級高于”+“和”-“,不論怎樣進行重載,各運算符之間的優先級不會改變。有時在程序中希望改變某運算符的優先級,也只能使用加括號的方法 強制改變重載運算符的運算順序。
(5)重載不能改變運算符的結合性。
如,復制運算符”=“是右結合性(自右至左),重載后仍為右結合性。
(6)重載運算符的函數不能有默認的參數
否則就改變了運算符參數的個數,與前面第(3)點矛盾。
(7)重載的運算符必須和用戶定義的自定義類型的對象一起使用,其參數至少應有 一 個是類對象(或類對象的引用)。
也就是說,參數不能全部是 C++的標準類型,以防止用戶修改用于標準類型數據成 員的運算符的性質,
(8)用于類對象的運算符一般必須重載,但有兩個例外,運算符”=“和運算 符”&“不 必用戶重載。
復制運算符”=“可以用于每一個類對象,可以用它在同類對象之間相互賦值。因為系統已為每一個新聲明的類重載了一個賦值運算符,它的作用是逐個復制類中的 數據成員地址運算符&也不必重載,它能返回類對象在內存中的起始地址。
(9)應當使重載運算符的功能類似于該運算符作用于標準類型數據時候時所實現的功能。
例如,我們會去重載”+“以實現對象的相加,而不會去重載”+“以實現對象相 減的功能,因為這樣不符合我們對”+“原來的認知。
(10)運算符重載函數可以是類的成員函數,也可以是類的友元函數,還可以是既非類的成員函數也不是友元函數的普通函數
操作符重載
#if 1 #define _CRT_SECURE_NO_WARNINGS #include <iostream>using namespace std;class Complex { public:Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}friend Complex complexAdd(Complex &c1, Complex &c2);/*friend Complex operator+(Complex &c1, Complex &c2);friend Complex operator-(Complex &c1, Complex &c2);*/Complex complexAdd(Complex &another){Complex temp(this->a + another.a, this->b + another.b);return temp;}//2操作符重載寫在局部Complex operator+(Complex &another){Complex temp(this->a + another.a, this->b + another.b);return temp;}Complex operator-(Complex &another){Complex temp(this->a - another.a, this->b - another.b);return temp;}private:int a;//實數int b;//虛數 };Complex complexAdd(Complex &c1, Complex &c2) {Complex temp(c1.a + c2.a, c1.b + c2.b); //要訪問需要聲明為友元函數return temp; } void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();Complex c3 = complexAdd(c1, c2);c3.printComplex(); }void test02() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();Complex c3 = c1.complexAdd(c2);c3.printComplex(); } //1操作符重載寫在全局 #if 0 Complex operator+(Complex &c1, Complex &c2) //+ 相當于函數名,接收兩個參數//+ 左邊是 第一個參數//+ 右邊是 第二個參數 順序固定 {Complex temp(c1.a + c2.a, c1.b + c2.b);return temp; }Complex operator-(Complex &c1, Complex &c2) {Complex temp(c1.a - c2.a, c1.b - c2.b);return temp; }#endif //全部操作符重載調用 void test03() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();//Complex c3 = operator+(c1, c2); //ok//等價于Complex c3 = c1 + c2; //此種為隱式寫法// c1 + c2 等價于 operator+(c1,c2) 全局的調用方式// c1 + c2 也等價于 c1.operator+(c2) 局部調用方式//所以局部調用方式和全局調用方式只能存在一個c3.printComplex(); } void test04() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();//Complex c3=c1.operator+(c2);//等價于Complex c3 = c1 + c2;c3.printComplex();Complex c4 = c1 - c2;c4.printComplex();Complex c5 = c1-c2-c1; //當 operator-函數 返回為元素時ok //c1-c2返回為匿名對象 //再調用函數 還為匿名對象 拷貝構造給c5//當 operator-函數返回引用時 錯誤 //c1-c2返回為為temp的別名//再調用函數時 temp已經析構 c1-c2變為亂碼 再調用函數仍然為亂碼c5.printComplex(); } int main(void) {cout << "------test01-----------" << endl;test01();cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();return 0; } #endif雙目運算符(有兩個參數):
#if 1 #define _CRT_SECURE_NO_WARNINGS #include <iostream>using namespace std;class Complex { public:/*friend Complex& operator+=(Complex &c1, Complex &c2);friend Complex& operator-=(Complex &c1, Complex &c2);*/Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}//2操作符重載寫在局部Complex& operator+=(Complex &another){this->a += another.a;this->b += another.b;return *this;}Complex& operator-=(Complex &another){this->a -= another.a;this->b -= another.b;return *this;}private:int a;//實數int b;//虛數 };//1操作符重載寫在全局 #if 0 Complex& operator+=(Complex &c1, Complex &c2) //+ 相當于函數名,接收兩個參數//+ 左邊是 第一個參數//+ 右邊是 第二個參數 順序固定 {c1.a += c2.a;c1.b += c2.b;return c1; }Complex& operator-=(Complex &c1, Complex &c2) {c1.a -= c2.a;c1.b -= c2.b;return c1; }#endif void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();(c1 += c2)+=c2; //(c1.operator+=(c2)).operator(c2)c1.printComplex();c2.printComplex(); } /* ( 1, 2i ) ( 2, 4i ) ( 5, 10i ) ( 2, 4i ) */ //全部操作符重載調用int main(void) {cout << "------test01-----------" << endl;test01();/*cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0; } #endif單目運算符:
#if 1 #define _CRT_SECURE_NO_WARNINGS #include <iostream>using namespace std;class Complex { public:/*friend Complex& operator++(Complex &c1);friend Complex& operator--(Complex &c12);friend const Complex& operator++(Complex &c1, int);*/Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}//2操作符重載寫在局部Complex& operator++(){this->a ++;this->b ++;return *this;}Complex& operator--(){this->a --;this->b --;return *this;}const Complex& operator++(int) { //亞元Complex temp(this->a, this->b);this->a++;this->b++;return *this;}private:int a;//實數int b;//虛數 };//1操作符重載寫在全局 #if 0 //重載的前置加加 Complex& operator++(Complex &c1) //+ 相當于函數名,接收兩個參數//+ 左邊是 第一個參數//+ 右邊是 第二個參數 順序固定 {c1.a ++;c1.b ++;return c1; }Complex& operator--(Complex &c1) {c1.a--;c1.b--;return c1; }#endif //重載的后置加加 不可以用多次 所以用const限制 #if 0 const Complex& operator++(Complex &c1, int) { Complex temp(c1.a, c1.b);c1.a++;c1.b++;return c1; } #endif void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();++c1;c1.printComplex();/*++c1;c1.printComplex();*/} /* ( 1, 2i ) ( 2, 4i ) ( 2, 3i ) ( 3, 4i ) */ void test02() {int a = 0;//a++++; 編譯錯誤 后置加加不可多次Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();c1++; //后置加加返回值添加const 使得c1++++ 編譯錯誤c1.printComplex(); } /* ( 1, 2i ) ( 2, 4i ) ( 2, 3i ) */ int main(void) {cout << "------test01-----------" << endl;test01();cout << "------test02-----------" << endl;test02();/*cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0; } #endif左移右移操作符:
#if 1 #define _CRT_SECURE_NO_WARNINGS #include <iostream>using namespace std;class Complex { public:friend ostream& operator<<(ostream &os, Complex &c);friend istream& operator>>(istream &is, Complex &c);Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;} #if 0//左移操作符只能不能夠寫在成員函數里 只能寫在全局函數中 否則調用順序會變反 c1<<cout;ostream& operator<<(ostream &os) { //c1.operator<<(cout)os << "(" << this->a << "," << this->b << "i)";return os;} #endif//2操作符重載寫在局部private:int a;//實數int b;//虛數 };//1操作符重載寫在全局 #if 1 //重載的前置加加 ostream& operator<<(ostream &os, Complex &c) {os << "(" << c.a << "," << c.b << "i)";return os; } istream& operator>>(istream &is, Complex &c) {cout << "a:";is >> c.a;cout << "b:";is >> c.b;return is; } #endifvoid test01() {Complex c1(1, 2);Complex c2(2, 4);cout << c1 << endl;cin >> c2;c1.printComplex();c2.printComplex();//cout << c1; //operator<<(cout,c1) 全局ok 局部不ok//c1 << cout; ok} /**/int main(void) {cout << "------test01-----------" << endl;test01();/*cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0; } #endif總結
以上是生活随笔為你收集整理的C++基础11-类和对象之操作符重载1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv16-Sobel算子
- 下一篇: java 同步锁_Java多线程:syn