重载逻辑操作符,逗号操作符,前置++操作符和后置++操作符

目录

1、重载逻辑操作符

1、原生逻辑操作符

2、重载逻辑操作符 

2、重载逗号操作符

1、原生逗号操作符 

2、重载逗号操作符

3、重载前置++操作符和后置++操作符

1、值得思考的问题

2、++操作符重载

4、小结


1、重载逻辑操作符

1、原生逻辑操作符

逻辑运算符的原生语义 

   -操作数只有两种值(true和false) 

   -逻辑表达式不用完全计算就能确定最终值 

   -最终结果只能是true或者false

编程实验

逻辑表达式   test.cpp

#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;  
}  

  

2、重载逻辑操作符 

逻辑操作符可以重载吗? 重载逻辑操作符有什么意义?

编程实验

重载逻辑操作符   test.cpp

#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& 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);  
      
    if( func(t0) && func(t1) )  //operator && (func(0),func(1))
    {  
        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;  
}  

 

在C语言已经知道函数参数调用顺序是不确定的,且目前大多数为从右到左(函数调用约定)

问题的本质分析 

    ① C++通过函数调用扩展操作符的功能 

    ② 进入函数体前必须完成所有参数的计算 

    ③ 函数参数的计算次序是不定的 

    ④ 短路法则完全失效

逻辑操作符重载后无法完全实现原生的语义!!!

一些有用的建议 

   -实际工程开发中避免重载逻辑操作符 

   -通过重载比较操作符代替逻辑操作符重载 

   -直接使用成员函数代替逻辑操作符重载 

   -使用全局函数对逻辑操作符进行重载  


2、重载逗号操作符

1、原生逗号操作符 

逗号操作符可以构成逗号表达式 

    -逗号表达式用于将多个子表达式连接为一个表达式 

    -逗号表达式的值为最后一个子表达式的值 

    -逗号表达式中的前N-1个子表达式可以没有返回值 

    -逗号表达式按照从左向右的顺序计算每个子表达式的值

实例分析

逗号表达式的示例   test.cpp

#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),  
        (3, 4, 5),  
        (6, 7, 8)  
    };  
      
    int i = 0;  
    int j = 0;  
      
    while( i < 5 )      
        func(i),  
      
    i++;  
          
    for(i=0; i<3; i++)  
    {  
        for(j=0; j<3; j++)  
        {  
            cout << a[i][j] << endl;  
        }  
    }  
      
    (i, j) = 6;  
      
    cout << "i = " << i << endl;  
    cout << "j = " << j << endl;  
  
    return 0;  
}  

2、重载逗号操作符

在C++中重载逗号操作符是合法的 

使用全局函数对逗号操作符进行重载 

重载函数的参数必须有—个是类类型 

重载函数的返回值类型必须是引用 

Class& operator , (const Class& a, const Class& b)   
{  
    return const_cast<Class&>(b);  
}   

编程实验

重载逗号操作符   test.cpp

#include <iostream>  
#include <string>  
  
using namespace std;  
  
class Test  
{  
    int mValue;  
public:  
    Test(int i)  
    {  
        mValue = i;  
    }  
    int value()  
    {  
        return mValue;  
    }  
};  
Test& operator , (const Test& a, const Test& b)  
{  
    return const_cast<Test&>(b);  
}  
Test func(Test& i)  
{  
    cout << "func() : i = " << i.value() << endl;  
      
    return i;  
}  
  
int main()  
{     
    Test t0(0);  
    Test t1(1);  
    Test tt = (func(t0), func(t1));         // operator , (func(t0),func(t1))  
      
    cout << tt.value() << endl; // 1  
      
    return 0;  
} 

 (不可预期)

搞笑的是当注释操作符重载后 

(可预期)

问题的本质分析 

    ① C++通过函数调用扩展操作符的功能 

    ② 进入函数体前必须完成所有参数的计算 

    ③ 函数参数的计算次序是不定的 

    ④ 重载后无法严格从左向右计算表达式

工程中不要重载逗号操作符!!!

 

3、重载前置++操作符和后置++操作符

1、值得思考的问题

下面的代码有没有区别?为什么? 

i++; // i的值作为返回值, i自增1   
++i; // i自增1, i的值作为返回值    

编程实验 

真的有区别吗? test.cpp 

int main()  
{  
    int i = 0;  
  
    i++;  
  
    ++i;  
  
    return 0;  
} 

 

在工程中,编译器会在忽略返回值情况下进行优化,即在工程中它们没有区别!!!

意想不到的事实

    -现代编译器产品会对代码进行优化 

    -优化使得最终的二进制程序更加高效 

    -优化后的二进制程序丢失了C/C++的原生语义 

    -不可能从编译后的二进制程序还原C/C++程序 

    -C/C++开发的软件无法完全反编译!

   ++操作符可以重载吗? 如何区分前置++和后置++?

2、++操作符重载

++操作符可以被重载 

    -全局函数成员函数均可进行重载 

    -重载前置++操作符不需要额外的参数 

    -重载后置++操作符需要—个int类型的占位参数 

编程实验

++操作符的重载    test.cpp 

#include <iostream>    
#include <string>    
    
using namespace std;    
    
class Test    
{    
    int mValue;    
public:    
    Test(int i)    
    {    
        mValue = i;    
    }    
        
    int value()    
    {    
        return mValue;    
    }    
    
    // 重载前置++    
    Test& operator ++ ()    
    {    
        ++mValue;    
            
        return *this;    
    }    
    
    // 重载后置++    
    Test operator ++ (int) //引入了第二个对象,效率...
    {    
        Test ret(mValue); //根据C中i++的语义,先返回值,再自加  
            
        mValue++;    
            
        return ret;    
    }    
};    
    
int main()    
{    
    Test t(0);    
        
    Test tt = t++;    
      
    cout << tt.value() << endl;  
      
    cout << t.value() << endl;  
        
    ++t;    
      
    cout << t.value() << endl;  
        
    return 0;    
}  

  

对于基础类型的变量 

    -前置++的效率与后置++的效率基本相同 

    -根据项目组编码规范进行选择 

对于类类型的对象 

    -前置++的效率高于后置++ 

    -尽量使用前置++操作符提高程序效率

编程实验

复数类的进—步完善     class Complex

Complex.h

#ifndef _COMPLEX_H_  
#define _COMPLEX_H_  
  
class Complex  
{  
    double a;  
    double b;  
public:  
    Complex(double a = 0, double b = 0);  
    double getA();  
    double getB();  
    double getModulus();  
      
    Complex operator + (const Complex& c);  
    Complex operator - (const Complex& c);  
    Complex operator * (const Complex& c);  
    Complex operator / (const Complex& c);  
      
    bool operator == (const Complex& c);  
    bool operator != (const Complex& c);  
      
    Complex& operator = (const Complex& c);  
      
    Complex& operator ++ ();  
    Complex operator ++ (int);  
};  
  
#endif  

Complex.cpp

#include "Complex.h"  
#include "math.h"  
  
Complex::Complex(double a, double b)  
{  
    this->a = a;  
    this->b = b;  
}  
  
double Complex::getA()  
{  
    return a;  
}  
  
double Complex::getB()  
{  
    return b;  
}  
  
double Complex::getModulus()  
{  
    return sqrt(a * a + b * b);  
}  
  
Complex Complex::operator + (const Complex& c)  
{  
    double na = a + c.a;  
    double nb = b + c.b;  
    Complex ret(na, nb);  
      
    return ret;  
}  
  
Complex Complex::operator - (const Complex& c)  
{  
    double na = a - c.a;  
    double nb = b - c.b;  
    Complex ret(na, nb);  
      
    return ret;  
}  
  
Complex Complex::operator * (const Complex& c)  
{  
    double na = a * c.a - b * c.b;  
    double nb = a * c.b + b * c.a;  
    Complex ret(na, nb);  
      
    return ret;  
}  
  
Complex Complex::operator / (const Complex& c)  
{  
    double cm = c.a * c.a + c.b * c.b;  
    double na = (a * c.a + b * c.b) / cm;  
    double nb = (b * c.a - a * c.b) / cm;  
    Complex ret(na, nb);  
      
    return ret;  
}  
      
bool Complex::operator == (const Complex& c)  
{  
    return (a == c.a) && (b == c.b);  
}  
  
bool Complex::operator != (const Complex& c)  
{  
    return !(*this == c);  
}  
      
Complex& Complex::operator = (const Complex& c)  
{  
    if( this != &c )  
    {  
        a = c.a;  
        b = c.b;  
    }  
      
    return *this;  
}  
  
Complex& Complex::operator ++ ()  
{  
    a = a + 1;  
    b = b + 1;  
      
    return *this;  
}  
      
Complex Complex::operator ++ (int)  
{  
    Complex ret(a, b);  
      
    a = a + 1;  
    b = b + 1;  
      
    return ret;  
}  

main.cpp

#include<iostream>  
#include"Complex.h"  
using namespace std;  
int main()  
{  
    Complex c(1,2);  
      
    ++c;  
      
    cout<<c.getA()<<endl;  
    cout<<c.getB()<<endl;  
      
    c++;  
      
    cout<<c.getA()<<endl;  
    cout<<c.getB()<<endl;  
      
      
} 

  

 

4、小结

C++从语法上支持逻辑操作符重载 

重载后的逻辑操作符不满足短路法则 

工程开发中不要重载逻辑操作符 

通过重载比较操作符替换逻辑操作符重载 

通过专用成员函数替换逻辑操作符重载

        

逗号表达式从左向右顺序计算每个子表达式的值 

逗号表达式的值为最后—个子表达式的值 

操作符重载无法完全实现逗号操作符的原生意义 

工程开发中不要重载逗号操作符 

 

编译优化使得最终的可执行程序更加高效 

前置++操作符和后置++操作符都可以被重载 

++操作符的重载必须符合其原生语义 

对于基础类型,前置++与后置++的效率几乎相同 

对于类类型,前置++的效率高于后置++ 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值