欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数

程序员文章站 2024-02-01 10:27:22
++操作符重载 ++操作符分为前置++和后置++,比如: ++a; a++; ++操作符可以进行全局函数或成员函数重载 重载前置++操作符不需要参数 重载后置++操作符需要一个int类型的占位参数 前置++操作符的返回值为*this 后置++操作符的返回值为临时对象 例如: 隐式转换之explici ......

++操作符重载

  • ++操作符分为前置++后置++,比如: ++a;  a++;
  • ++操作符可以进行全局函数成员函数重载
  • 重载前置++操作符不需要参数
  • 重载后置++操作符需要一个int类型的占位参数
  • 前置++操作符的返回值为*this
  • 后置++操作符的返回值为临时对象

例如:

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);       ++mValue;   //改变实际对象的内容       return ret;  //返回临时对象 } };

 

 

隐式转换之explicit关键字

当我们在使用两个不同类型的数值运算时,编译器便会执行隐式转换,会将两者类型转为相同

转换规则如下所示:

 21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数

比如:

int a= -2000;
double b = i;         //将i隐式转换为double类型, b=-2000

 

隐式转换的隐患

隐式转换有时会因为类型不同,得到的结果大有不同,也是常见bug之一.

参考以下示例:

unsigned int a= 1000;

int b= -2000;

cout<<a+b<<endl;                     //将b隐式转换为unsigned int类型

运行打印:

4294966296

答案并非是-1000。

 

同样,我们使用构造函数时,也经常使用隐式转换

参考以下示例:

class  Test{
public:
       Test(unsigned int i)
       {
              cout<<"unsigned i= "<<i<<endl;
       } 
};

int main()
{  
    Test t1=-2;                //将-2 隐式转换为unsigned int 型
    return 0;
}

运行打印:

unsigned i= 4294967294

首先编译器通过-2来找只有一个参数的构造函数,发现它的参数是unsigned int,所以便将-2隐式转换为unsigned int,从而造成结果不同.

 

如何解决隐式转换

在构造函数声明的时候加上explicit关键字,便能使该函数只能进行显示转换,使用方法如下:

class  Test{
public:
       explicit Test(unsigned int i)
       {
              cout<<"unsigned i= "<<i<<endl;
       } 
};

添加后,再次编译Test t1=-2;时,就会报错了.

若添加explicit后,还想继续使用隐式转换,可以通过下面3钟方法使用隐式转换:

Test t1=(Test)-2;                   //C方式强制转换,不推荐
Test t1=static_cast<Test>(-2);     //C++方式强制转换
Test t1(-2);                      //手工调用构造函数

 

 

类型转换函数

在C++类中可以定义类型转换函数

  • 类型转换函数用于将类对象转换为其它类型,比如int
  • 方法是通过operator关键字重载其它类型,返回类型不需要填

参考以下示例:

class  Test{
int mValue;
public: Test(int i=0) { mValue=i; } operator int() { return mValue; } }; int main() { Test t(1000); int i=t; //等价于: i=t.operator int(); cout<<i<<endl; //i=1000 }

同样,也能支持类与类之间转换

不过类型转换函数可能会与构造函数冲突,比如:

class  Test;          

class Value{
public:
       Value()
       {  }
       Value(Test &t)        //Value类的构造函数
       {  } 
};

class  Test{

       int mValue;

public:
        Test(int i=0)
        {
              mValue=i;
        }

        operator  Value()        //Test类的类型转换函数
        {
              Value ret;
              return ret;
        }
};

int main()
{
       Test t(1000);
       Value Val=t;           //该行出错
}

编译出错,编译器不知道用哪个方式去初始化val对象,因为Value Val=t可以等价于:

Value Val(t);                               //执行Value类的构造函数 初始化
Value Val=t.operator Value ();             //执行Test类的类型转换函数

解决方法

Value(Test &t)构造函数,前面加上explicit关键字.

 

注意:在工程中,一般都是通过 to Type()成员函数来代替类的类型转换函数,比如QT的Qstring类: 有toInt()、toDouble()等成员函数来实现类型转换