C++学习笔记--陷阱!!逻辑操作符
2017-11-29 19:58
204 查看
逻辑操作符 && || !,在C语言中是经常使用的,C++是完全兼容了C的语法,那么又为什么说有陷阱呢?首先看逻辑操作符的原义:操作数只有两种值,真或假;逻辑表达式不需要全部计算完就能确定表达式的值;最终结果只能是真或假。
int a = 0;
int b = 1;
if(a && b)
{
...
...
}当我们确定了表达式a的值后就能判断出逻辑表达式为为假,这就是所谓的短路法则,同理表达式(b || a)也不需要计算所有表达式就能确定逻辑表达式的值。目前看来貌似并没有什么问题,那么陷阱从何而来呢?
前面对那么多操作符都进行过重载,那么我们对逻辑操作符进行重载是否可行呢?如果可行,有什么意义呢?先试试吧。
class Test
{
int mValue;
public:
Test(int v)
{
mValue = 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);
/**根据逻辑操作符来看,func(t0)计算后就能知道逻辑表达式的值**/
/**逻辑操作符的原义是遵守短路规则的*/
if( func(t0) && func(t1) )
cout << "Result is true!" << endl;
else
cout << "Result is false!" << endl;
cout << endl;
/**根据逻辑操作符来看,func(t1)计算后就能知道逻辑表达式的值*/
/**逻辑操作符的原义是遵守短路规则的*/
if( func(1) || func(0) )
cout << "Result is true!" << endl;
else
cout << "Result is false!" << endl;
return 0;
}首先定义一个类,含有一个私有成员变量,两个成员函数。接着就是对逻辑操作符进行重载,函数返回值是bool,因为逻辑表达式结果只有真或假,函数参数是Test类的两个const引用。返回值就是两个类对象的成员变量之间进行逻辑与或。最后还定义了一个测试函数,用于返回函数执行信息,main中定义了两个对象,分别用0和1初始化。接着就测试重载后的逻辑操作符。
下面看一下输出结果:
Test func(Test i) : i.value() = 1
Test func(Test i) : i.value() = 0
Result is false!
Test func(Test i) : i.value() = 0
Test func(Test i) : i.value() = 1
Result is true!
吃惊了吗?不应该将两条语句都打印出来啊,这样不就不遵守短路规则了吗?是不是有点疑惑?那么我们再来使用函数调用的方式使用重载后的逻辑操作符吧。
if( operator &&(func(t0),func(t1)) )
{
...
}
if( operator || (func(t1),func(t0)) )
{
...
}但是我们根据输出结果发现也是一样的,虽然结果还是一样的,但是我们似乎可以看出点什么了,它的本质是函数啊,函数在执行函数体之前应该干什么?当然是计算实参啊,不得把参数都给计算了才执行函数体吗?并且计算次序还是不确定的,这样似乎就解释了为什么每个逻辑表达式不遵守短路规则而会打印两条语句了。
那么结论来了:
C++从语法上支持逻辑操作符重载
由于重载逻辑操作符后改变了逻辑操作符本身的原义(不遵守短路规则),所以我们不建议对逻辑重载符进行重载。
实际工程开发中避免对逻辑操作符进行重载
可以通过重载比较操作符代替重载逻辑操作符,使用表达式的值和true或flase进行比较
可以直接使用成员函数代替逻辑操作符的重载
如果非要进行逻辑操作符重载的话可以使用全局函数对其进行重载
这真的是一个大大的陷阱!!!
int a = 0;
int b = 1;
if(a && b)
{
...
...
}当我们确定了表达式a的值后就能判断出逻辑表达式为为假,这就是所谓的短路法则,同理表达式(b || a)也不需要计算所有表达式就能确定逻辑表达式的值。目前看来貌似并没有什么问题,那么陷阱从何而来呢?
前面对那么多操作符都进行过重载,那么我们对逻辑操作符进行重载是否可行呢?如果可行,有什么意义呢?先试试吧。
class Test
{
int mValue;
public:
Test(int v)
{
mValue = 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);
/**根据逻辑操作符来看,func(t0)计算后就能知道逻辑表达式的值**/
/**逻辑操作符的原义是遵守短路规则的*/
if( func(t0) && func(t1) )
cout << "Result is true!" << endl;
else
cout << "Result is false!" << endl;
cout << endl;
/**根据逻辑操作符来看,func(t1)计算后就能知道逻辑表达式的值*/
/**逻辑操作符的原义是遵守短路规则的*/
if( func(1) || func(0) )
cout << "Result is true!" << endl;
else
cout << "Result is false!" << endl;
return 0;
}首先定义一个类,含有一个私有成员变量,两个成员函数。接着就是对逻辑操作符进行重载,函数返回值是bool,因为逻辑表达式结果只有真或假,函数参数是Test类的两个const引用。返回值就是两个类对象的成员变量之间进行逻辑与或。最后还定义了一个测试函数,用于返回函数执行信息,main中定义了两个对象,分别用0和1初始化。接着就测试重载后的逻辑操作符。
下面看一下输出结果:
Test func(Test i) : i.value() = 1
Test func(Test i) : i.value() = 0
Result is false!
Test func(Test i) : i.value() = 0
Test func(Test i) : i.value() = 1
Result is true!
吃惊了吗?不应该将两条语句都打印出来啊,这样不就不遵守短路规则了吗?是不是有点疑惑?那么我们再来使用函数调用的方式使用重载后的逻辑操作符吧。
if( operator &&(func(t0),func(t1)) )
{
...
}
if( operator || (func(t1),func(t0)) )
{
...
}但是我们根据输出结果发现也是一样的,虽然结果还是一样的,但是我们似乎可以看出点什么了,它的本质是函数啊,函数在执行函数体之前应该干什么?当然是计算实参啊,不得把参数都给计算了才执行函数体吗?并且计算次序还是不确定的,这样似乎就解释了为什么每个逻辑表达式不遵守短路规则而会打印两条语句了。
那么结论来了:
C++从语法上支持逻辑操作符重载
由于重载逻辑操作符后改变了逻辑操作符本身的原义(不遵守短路规则),所以我们不建议对逻辑重载符进行重载。
实际工程开发中避免对逻辑操作符进行重载
可以通过重载比较操作符代替重载逻辑操作符,使用表达式的值和true或flase进行比较
可以直接使用成员函数代替逻辑操作符的重载
如果非要进行逻辑操作符重载的话可以使用全局函数对其进行重载
这真的是一个大大的陷阱!!!
相关文章推荐
- OpenCV(C++接口)学习笔记4-Mat::operator = 的陷阱
- OpenCV(C++接口)学习笔记4-Mat::operator = 的陷阱(被黑过一次,此陷阱很隐秘)
- C++学习笔记之I/O流
- C++学习笔记
- 学习笔记(十):C++设置电脑静音
- C++学习笔记【转载】
- C++学习笔记
- c++引用学习笔记
- [Boolan] C++第五周学习笔记
- C++学习笔记32——构造函数
- C++学习笔记22,普通函数重载(1)
- 【C++学习02】《Essential C++》第二章(Procedural Programming)笔记
- C/C++中关于地址、指针和引用变量的学习笔记(四) : 函数
- 设计模式C++学习笔记之十六(Observer观察者模式)
- C++函数学习笔记
- Effective C++ 学习笔记(23)
- C++学习笔记 数组对象
- C++PrimerPlus第八章学习笔记——函数探幽
- c++学习笔记:直接排序
- c++指针学习笔记--交换两个字符串数据