邏輯操作符的陷阱(三十二)
阿新 • • 發佈:2018-05-24
C++ 重載邏輯操作符 邏輯操作符陷阱 比較操作符 我們今天來看看邏輯操作符,它的原生語義是:操作數只有兩種值(true 和 false),邏輯表達式不用完全計算就能確定最終值,其最終結果只能是 true 或者 false。
下來我們來看個編程實驗
#include <iostream> #include <string> using namespace std; int func(int i) { cout << "int func(int i): i = " << i << endl; return i; } int main() { if( func(0) && func(1) ) { cout << "Result is true!" << endl; } else { cout << "Result is false!" << endl; } cout << endl; if( func(0) || func(1) ) { cout << "Result is true!" << endl; } else { cout << "Result is false!" << endl; } return 0; }
我們利用在 C 語言中所學的知識,輕易可知第一個輸出 false,第二個輸出 true。並且第一個只打印出 func(0),第二個兩個都會打印出。我們來看看編譯結果
結果是這樣的,那麽這塊是否沒有什麽可講的嗎?邏輯操作符可以重載嗎?重載邏輯 操作符有什麽意義?我們看個示例代碼
#include <iostream> #include <string> using namespace std; class Test { int mValue; public: Test(int v) { mValue = v; } int value() const { return mValue; } }; bool operator && (const Test& r, const Test& l) { return r.value() && l.value(); } bool operator || (const Test& r, const Test& l) { return r.value() || l.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); if( func(t0) && func(t1) ) { cout << "Result is true!" << endl; } else { cout << "Result is false!" << endl; } cout << endl; if( func(1) || func(0) ) { cout << "Result is true!" << endl; } else { cout << "Result is false!" << endl; } return 0; }
我們看到重載了邏輯操作符,在 func 函數中傳入的是 Test 對象,然後看看編譯結果是否和之前的一樣呢?
我們看到雖然最後的結果是一樣的,但是調用 func 函數和之前不同了。兩次兩個都調用了,這是怎麽回事呢?我們回到操作符重載的本質來看,它是函數重載,我們試著寫下它的原型,如下
#include <iostream> #include <string> using namespace std; class Test { int mValue; public: Test(int v) { mValue = v; } int value() const { return mValue; } }; bool operator && (const Test& r, const Test& l) { return r.value() && l.value(); } bool operator || (const Test& r, const Test& l) { return r.value() || l.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); if( operator && (func(t0), func(t1)) ) { cout << "Result is true!" << endl; } else { cout << "Result is false!" << endl; } cout << endl; if( operator || (func(1), func(0)) ) { cout << "Result is true!" << endl; } else { cout << "Result is false!" << endl; } return 0; }
我們看到在第 43 和 54 行寫成這樣的形式,再次編譯看看
結果和之前的是一樣的,這便證明了操作符重載的本質是函數重載。C++ 通過函數調用擴展操作符的功能,進入函數體前必須完成所有參數的計算。函數參數的計算次序是不定的,短路法則則完全失效。因此,邏輯操作符重載後無法完全實現原生的語義。
我們通常在實際工程開發中避免重載邏輯操作符,通過重載比較操作符代替邏輯操作符重載。直接使用成員函數代替邏輯操作符重載,使用全居函數對邏輯操作符進行重載。通過對邏輯操作符重載的學習,總結如下:1、C++ 從語法上支持邏輯操作符重載,重載後的邏輯不滿足短路法則。2、工程開發中不要重載邏輯操作符;3、通過重載比較操作符替換邏輯操作符重載;4、通過專用成員函數替換邏輯操作符重載。
歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083。
邏輯操作符的陷阱(三十二)