1.1 逻辑操作符
1.1.1 逻辑运算符的原生意义
- 操作数只用两种值(true 和 false)
- 逻辑表达式不用
完全计算就能确定最终值(短路规则) - 最终结果只能是true或者 false
1.1.2 原生语义举例
int func(int i)
{
cout<<"int func(int i) : i= "<< i<<endl;
return i;
}
int main()
{
int a = 0;
int b = 1;
//if(a&&b)
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;
}
- 注意分析结果,以及实验的目的

1.1.3 逻辑操作符是否可以重载
- 逻辑操作符可以重载吗?
- 重载逻辑操作符有什么意义?
using namespace std;
class Test{
private:
int i;
public:
Test(int i)
{
this->i =i;
}
int value() const
{
return i;
}
};
bool operator&&(const Test&obj1,const Test&obj2) //&&重载
{
return (obj1.value() && obj2.value());
}
bool operator||(const Test&obj1,const Test&obj2) // ||重载
{
return (obj1.value() || obj2.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(t1) ||func(t0))
{
cout<<"result is true"<<endl;
}
else{
cout<<"result is false"<<endl;
}
return 0;
}
- 结果

1.1.4 问题本质 - C++通过函数调用扩展操作符的功能
- 进入函数体前必须完成所有参数的计算
- 函数参数的计算次序是不定的
- 短路法则完全失效
1.1.5 建议
- 实际工程中开发中避免虫子逻辑操作符
- 通过重载比较操作符代替逻辑操作符重载
- 直接使用成员函数代替逻辑操作符重载
- 使用全局函数对逻辑操作符进场重载
1.2 逗号操作符
1.2.1逗号操作(,)
逗号操作(,)可以构成逗号表达式
- 逗号表达式用于将多个子表达式连接为一个表达式
- 逗号表达式的值为最后一个子表达式的值
- 逗号表达式中的前 N-1个子表达式可以没有返回值
- 逗号表达式按照从左向右的顺序计算每个子表达式的值
- exp1,exp2,exp3,…,expN
1.2.2 案例
- 案例1
using namespace std;
void func(int i)
{
cout<<"func() i ="<<i <<endl;
}
int main()
{
int a[3][3] = {
(1,2,3),
(4,5,6),
(7,8,9)
};
int i =0;
int j =0;
while(i<5)
func(i),
i++;
cout<< endl;
cout<<"======================================"<<endl;
for( i =0;i<3;i++)
{
for(j=0;j<3;j++)
{
cout<< a[i][j]<<endl;
}
}
cout<< endl;
cout<<"======================================"<<endl;
(i,j)=10; //dot
cout<<"i= "<<i <<endl;
cout<<"j= "<<j <<endl;
return 0;
}
- 结果:

- 案例2
void func(int i)
{
cout<<"func() i ="<<i <<endl;
}
int main()
{
int a[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
int i =0;
int j =0;
while(i<5)
{
func(i);
i++;
}
cout<< endl;
cout<<"======================================"<<endl;
for( i =0;i<3;i++)
{
for(j=0;j<3;j++)
{
cout<< a[i][j]<<endl;
}
}
cout<< endl;
cout<<"======================================"<<endl;
(i,j)=10; //dot
cout<<"i= "<<i <<endl;
cout<<"j= "<<j <<endl;
return 0;
}
- 结果

1.2.3 重载逗号操作符
- 在C++中重载逗号操作符时合法的
- 使用全局函数对逗号操作符进行重载
- 重载函数的参数必须有一个是类类型
- 重载函数的返回值类型必须是引用
class& operator,(const class&a,const class&b)
{
return const_cast<class&>(b); //这里我们返回的是第二个参数,对应“,”表达式返回值是最后一个函数
}
1.2.4 示例代码
class Test
{
private:
int mvalue;
public:
Test(int value)
{
this->mvalue = value;
}
int value()
{
return mvalue;
}
};
Test& operator,(const Test&obj1,const Test&obj2)
{
return const_cast<Test&>(obj2);
}
Test func(Test&i)
{
cout <<"Test func(Test&i) : i = "<<i.value()<<endl;
return i;
}
int main()
{
Test t1(1);
Test t2(2);
Test tt = (func(t1),func(t2));
cout<< tt.value() <<endl;
return 0;
}
- 结果

class Test
{
private:
int mvalue;
public:
Test(int value)
{
this->mvalue = value;
}
int value()
{
return mvalue;
}
};
/*
Test& operator,(const Test&obj1,const Test&obj2)
{
return const_cast<Test&>(obj2);
}
*/
Test func(Test&i)
{
cout <<"Test func(Test&i) : i = "<<i.value()<<endl;
return i;
}
int main()
{
Test t1(1);
Test t2(2);
Test tt = (func(t1),func(t2));
cout<< tt.value() <<endl;
return 0;
}

1.2.5 问题的本质分析
- C++通过函数调用扩展操作符的功能
- 进入函数体前必须完成所有参数的计算
- 函数参数的计算次序是不定的
- 重载后无法严格从左向右计算表达式
注意: 实际中是完全没有必要重载逗号操作符的
1.3 前置操作符和后置操作符
1.3.1
1.3.2
1.3.3
1.4 类型转换函数上
1.4.1标准数据类型转换
- 标准数据类型之间会进行隐式类型安全转换(小类型转换成大类型)
- 转换规则如下:

- 举例
short s ='a';
cout<<"sizeof(s + 'b') = "<< sizeof(s+'b')<<endl; //结果是4 ,意外不?
1.4.2 思考
- 普通类型和类类型之间能否进行类型转换
- 类类型之间能否进行类型转换?
1.4.3 再论构造函数
- 构造函数可以定义不同类型的参数
- 参数满足下列条件时成为
转换构造函数- 有且仅有一个参数
- 参数是基本类型
- 参数是其他类类型
1.4.4 旧式的C语言强制类型转换
- 编译器尽力尝试的结果是隐式类型
- 隐式类型转换
- 会让程序以意想不到的方式进行工作
- 是工程中
bug的重要来源
class Test
{
private:
int mvalue;
public:
Test()
{
mvalue =0;
}
Test(int value)
{
this->mvalue = value;
}
Test operator+(const Test&obj)
{
Test ret(mvalue + obj.mvalue);
return ret;
}
int value()
{
return mvalue;
}
};
int main()
{
Test t;
t = 4 ; // <====> t = Test(4);
cout<<"t.value = "<<t.value()<<endl;
cout<<endl;
cout<<"====================================="<<endl;
Test r;
r =t + 10; // Test operator+(const Test&obj)
// r =t + Test(10); 编译器自动进行了隐式类型转换,导致bug的出现
cout<<"r.value = "<<r.value()<<endl;
return 0;
}

1.4.5 避免自动转换方法
- 工程中通过
explicit关键字杜绝编译器的转换尝试 - 转换构造函数被
explicit修饰时只能进行显示转换 - 转换方式
- static_cast (value)
- ClassName(value)
- (ClassName)(value); //不推荐
1.5 类型转换函数下
1.5.1 问题
-
类类型能否类型转换成普通类型?不能直接转换
1.5.2 定义类型转换函数 -
案例1
class Test
{
private:
int mvalue;
public:
Test(int value =0)
{
this->mvalue = value;
}
int value()
{
return mvalue;
}
};
int main()
{
Test t(10);
int i =t;
return 0;
}

- 案例2 //注意比较两个案例的区别
class Test
{
private:
int mvalue;
public:
Test(int value =0)
{
this->mvalue = value;
}
int value()
{
return mvalue;
}
operator int()
{
return mvalue;
}
};
int main()
{
Test t(10);
int i =t; // 隐式类型转换可能导致bug
cout <<"i = "<<i<<endl;
return 0;
}

1.5.3 类类型之间的相互转换
类型转换函数 VS 转换构造函数
类型转换函数 和 转换构造函数 是互逆的
- 失败举例
// Value 中有转换构造函数
//Test中有类型转换函数
//编译器不知道调用哪个了
//解决方式,在转换构造函数中加上 explicit关键字
class Test;
class Value
{
public:
Value()
{
}
Value(Test&t)
{
}
};
class Test
{
private:
int mvalue;
public:
Test(int value =0)
{
this->mvalue = value;
}
int value()
{
return mvalue;
}
operator Value()
{
Value ret;
return ret;
}
};
int main()
{
Test t(10);
Value v =t;
return 0;
}

1.5.4 结论
- 类型转换函数可能与转换构造函数冲突
- 无法抑制隐式的类型转换函数调用
- 工程中以
Type toType()的公有成员代替类型转换函数
using namespace std;
class Test;
class Value
{
public:
Value()
{
}
Value(Test&t)
{
}
};
class Test
{
private:
int mvalue;
public:
Test(int value =0)
{
this->mvalue = value;
}
int value()
{
return mvalue;
}
Value toValue() // 公有成员代替类型转换函数
{
Value ret;
return ret;
}
};
int main()
{
Test t(10);
Value v =t.toValue();
return 0;
}
1.5.5 QT中通过共有函数进行类型转换
int main()
{
QString str = "";
int i = 0;
double d = 0;
short s = 0;
str = "-255";
i = str.toInt();
d = str.toDouble();
s = str.toShort();
qDebug() << "i = " << i << endl;
qDebug() << "d = " << d << endl;
qDebug() << "s = " << s << endl;
return 0;
}
参考一 : 狄泰软件课程
如有侵权:请联系邮箱 1986005934@qq.com
本文深入探讨C++中的逻辑操作符、逗号操作符、类型转换等核心概念,包括操作符的原生意义、重载规则及类型转换机制,通过实例解析操作符的工作原理和潜在陷阱。
1342

被折叠的 条评论
为什么被折叠?



