逻辑操作符的陷阱(三十二)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逻辑操作符的陷阱(三十二)相关的知识,希望对你有一定的参考价值。

        我们今天来看看逻辑操作符,它的原生语义是:操作数只有两种值(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

以上是关于逻辑操作符的陷阱(三十二)的主要内容,如果未能解决你的问题,请参考以下文章

第三十二篇 vue

Django笔记三十二之session登录验证操作

第三十二课Qt中的文件操作

第三十二篇 玩转数据结构——AVL树

Powershell管理系列(三十二)PowerShell操作之开启终端Powershell远程管理

C++--智能指针逻辑操作符的陷阱