C++语法基础--转换操作符,重载确定

1.转换操作符
  *将类类型值转变为其他类型值的转换。
  *转换操作符在类定义体内声明,在保留字operator之后跟着转换的目标类型, operator type();
  *转换函数必须是成员函数,不能指定返回类型(但必须显示返回一个指定类型的值),并且形参表必须为空
  *只要存在转换,编译器将在可以使用内置转换的地方自动调用它。 
 Example:
   class MyInt
{
  public:
        MyInt(int i):x(i){}
        operator int(){return x;}
  private:
   size_t x;                                                    
};


int main()
{
    MyInt mi(1);
    cout<<mi+1<<endl;
//2,MyInt并没有重载operator+(),但还是输出了正确的结果
   return 0;
}


2.只能应用一次类类型转换(既,转换不具有传递性)
  Example:
  class MyInt
{
  public:
        MyInt(int i):x(i){}
        operator int(){return x;}
  private:
   size_t x;                                                    
};


class Iterger
 {
  public:
  Iterger(int i):y(i){}
  operator MyInt(){return y;}
    private:
 size_t y;
 
};


int main()
{
   
     Iterger itg(1);
     MyInt mi=itg;
//ok ,itg先转换为MyInt,然后复制给mi 
     cout<<mi+1<<endl;//2
     cout<<itg+1;//error,itg先转换为MyInt,但不会再继续转为int;
     
     return 0;
}


3.实参匹配和类型转换
  (1)实参匹配和多个转换操作符
       *如果两个转换操作符都可以在一个调用中,而且在转换函数之后存在标准转换,则根据该标准转换的类别选择最佳匹配

 

Example:

   class MyInt
{
  public:
        MyInt(int i):x(i){}
         MyInt(double i):x(i){}
        operator int(){return x;}
        operator double(){return x;}
  private:
   size_t x;                                                    
};


void ifun(int x)
{
cout<<x<<endl;
}


void dfun(double x)
{
cout<<x<<endl;
}


void ldfun(long double x)
{
cout<<x<<endl;
}


int main()
{
   MyInt mi(1);
   ifun(mi);
 //ok, operator int()
   dfun(mi);  //ok,operator double()
   ldfun(mi); //error,存在二义性
}

Tips:避免二义性的最好方法是,保证最多只有一种途径将一个类型转换为另一个类型



4.重载确定和类的实参

   *在需要转换函数的实参时,编译器自动应用类的转换操作符或构造函数
   *函数重载确定由三步骤组成
     (1)确定候选函数函数集合(被调用函数同名的函数)
     (2)选择可行的函数(形参数目和类型与函数调用中的实参相匹配的候选函数,如有转换操作,还需确定哪个转换操作来匹配每个形参)
     (3)选择最佳匹配的函数

  *多个转换和重载容易出现二义性(如果可以使用不同转换操作,编译器则认为这两个转换是一样好的匹配)

  

Example:

    class MyInt
{
  public:
        MyInt(int i):x(i){}
         MyInt(double i):x(i){}
        operator int(){return x;}
        operator double(){return x;}
  private:
   size_t x;                                                    
};


void fun(int x)
{
cout<<x<<endl;
}


void fun(double x)
{
cout<<x<<endl;
}


void ldfun(long double x)
{
cout<<x<<endl;
}


int main()
{
   MyInt mi(1);
   fun(mi);
 //error,call of overloaded 'fun(MyInt&)' is ambiguous
   fun(mi);  //error,call of overloaded 'fun(MyInt&)' is ambiguous
   ldfun(mi); //error,conversion from 'MyInt' to 'long double' is ambiguous
}


  Tips:
   解决方法:显式强制转换以消除二义性
  int main()
{
   MyInt mi(1);
   fun(static_cast<int>(mi));
 //1
   fun(static_cast<double>(mi));  //1
  
}


5.标准转换和构造函数
   *多个转换构造函数的重载确定
     class MyInt
{
  public:
        MyInt(int i):x(i){}
        operator int(){return x;}
  private:
   size_t x;                                                    
};


  class Interger
{
  public:
        Interger(int i):x(i){}
        operator int(){return x;}
  private:
   size_t x;                                                    
};


void fun(MyInt x)
{
cout<<x<<endl;
}


void fun(Interger x)
{
cout<<x<<endl;
}




int main()
{
   fun(1);
//Error,call of overloaded 'fun(int)' is ambiguous


   return 0;
}


 解析:
      fun(1)存在二义性是因为MyInt,Iterger的构造函数都接受int型的参数,编译器无法确定调用哪个构造函数转换来匹配void fun(MyInt x),void fun(Interger x)

 解决方法:显式调用构造函数
   int main()
{
   fun(MyInt(1));
//1
   fun(Interger(2));//2
   
   return 0;
}
     





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值