目錄
- 1. 結論
- 2. 邏輯運算子多載
- 3. 逗號運算子多載
1. 結論
前面兩次筆記都是C++中可以多載且無副作用的運算子,本次筆記比較特殊,主要列出兩個C++語法允許多載、但在工程中不應該(不允許)多載的運算子:
- 邏輯運算子
&&和|| - 逗號運算子
,構成的逗號運算式
這兩個運算子在工程中不允許多載的原因是:多載后無法完全實作運算子的原生語意,
2. 邏輯運算子多載
先來回憶一下邏輯運算子的原生語意
- 運算元只有true和false兩種值
- 邏輯運算式不需要完全計算就能確定最終結果(短路法則)
- 最終結果也只能是true或者false
C++語法是允許多載邏輯運算子的,看下面的示例代碼
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test(int v)
{
mValue = https://www.cnblogs.com/songhe364826110/p/v;
}
int value() const
{
return mValue;
}
};
bool operator && (const Test &l, const Test &r)
{
return l.value() && r.value();
}
bool operator || (const Test &l, const Test &r)
{
return l.value() || r.value();
}
Test func(Test i)
{
cout <<"Test func(Test i) : i.value() = " << i.value() << endl;
return i;
}
int main()
{
Test t0(0);
Test t1(1);
/*
* 根據短路法則,期望的正確輸出為:
* Test func(Test i) : i.value() = 0
* Result is false!
*/
if( func(t0) && func(t1) )
{
cout << "Result is true!" << endl;
}
else
{
cout << "Result is false!" << endl;
}
cout << endl;
/*
* 根據短路法則,期望的正確輸出為:
* Test func(Test i) : i.value() = 1
* Result is true!
*/
if( func(1) || func(0) )
{
cout << "Result is true!" << endl;
}
else
{
cout << "Result is false!" << endl;
}
return 0;
}

代碼中注釋了我們期待的正確輸出,但實際運行結果一個都沒對上,為什么呢?
- 運算子多載的本質是通過函式呼叫擴展運算子的功能,47行和63行的if條件分別等價于
operator && (func(t0), func(t1))和operator || (func(t1), func(t0)) - 多載函式在進入函式體之前必須完成所有引數的計算,而函式引數的計算順序是不確定的
- 短路法則完全失效,邏輯運算子多載后無法完全實作原生語意
因此,在工程中應當避免多載邏輯運算子,建議采用多載比較運算子或提供成員函式的方式,來代替多載邏輯運算子,
3. 逗號運算子多載
逗號運算子,可以構成逗號運算式,下面是逗號運算式的原生語意
- 逗號運算式用于將多個子運算式連接為一個運算式,如
exp1, exp2, exp3, ... , expN - 逗號運算式中前N-1個子運算式可以沒有回傳值,最后一個子運算式必須有回傳值
- 逗號運算式的最終結果為最后一個子運算式的值
- 逗號運算式嚴格按照從左向右的順序計算每個子運算式的值
#include <iostream>
#include <string>
using namespace std;
void func(int i)
{
cout << "func() : i = " << i << endl;
}
int main()
{
int a[3][3] =
{
(0, 1, 2), //逗號運算式,等價于a[3][3] = {2, 5, 8,};
(3, 4, 5),
(6, 7, 8)
};
int i = 0;
int j = 0;
while (i < 5)
func(i), //逗號運算式,等價于func(i), i++;
i++;
cout << endl;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
cout << a[i][j] << endl;
}
}
cout << endl;
(i, j) = 6; //逗號運算式,等價于 j = 6;
cout << "i = " << i << endl;
cout << "j = " << j << endl;
return 0;
}

在C++中多載逗號運算子是合法的,多載函式的引數必須有一個是型別別,且多載函式的回傳值型別必須是參考
Class &operator , (const Class &a, const Class &b)
{
return const_cast<Class &>(b);
}
看下面的示例代碼
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test(int i)
{
mValue = https://www.cnblogs.com/songhe364826110/p/i;
}
int value()
{
return mValue;
}
};
Test &operator , (const Test &a, const Test &b)
{
return const_cast(b);
}
Test func(Test &i)
{
cout <<"func() : i = " << i.value() << endl;
return i;
}
int main()
{
Test t0(0);
Test t1(1);
/*
* 期望的正確輸出為:
* func() : i = 0
* func() : i = 1
* 1
*/
Test tt = (func(t0), func(t1));
cout << tt.value() << endl;
return 0;
}

雖然第44行輸出結果和預期相符,但第43行輸出和預期不符,原因和邏輯運算子多載一樣,都是由函式引數計算順序的不確定性造成的,也就是說:
- 逗號運算子多載后,構成的逗號運算式無法嚴格按照從左向右的順序計算各個子運算式
- 逗號運算子多載后無法完全實作原生語意
- 因此,在工程中不要多載逗號運算子
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/103675.html
標籤:C++
上一篇:C++類拷貝控制 深拷貝 淺拷貝
下一篇:淺談 Vector
