隐式转换

C++编译器在进行类型转换时,如果数据类型满足下面两种情况,编译器将会进行隐式转换(implicit conversions)

  1. C++内建类型(char,short,int,double)之间默认含有隐式转换
  2. class如果提供了单参数构造函数(single-argument constructors)隐式类型转换运算符(operator())这两个函数也支持隐式转换

class的隐式转换

单参数构造函数

单参数构造函数是指只用一个参数即可以调用的构造函数。该函数可以是只定义了一个参数,也可以是虽定义了多个参数但第一个参数以后的所有参数都有缺省值。

什么情况会发生隐式类型转换,和构造函数参数类型有关。

class Name
{
public:
    Name(const string &str): _str(str)
    {
        cout << "Invoke contructor, parameter: " << str << endl;
    }

    string _str;
};

int main()
{
    string s = "Hello World";
    Name name(s);

    string t = "HeHe";
    name = t;      // t隐式转换为Name类型,执行其构造函数

    // char ch = 'a';
    // name = ch; //Error 构造函数参数类型为string 而不是char
}

输出为

Invoke contructor, parameter: Hello World
Invoke contructor, parameter: HeHe
class Rational
{                                   // 有理数类
public:
    Rational(int numerator = 0,     // 转换int到
        int denominator = 1){}        // 有理数类Rational

    Rational(Name name){}             // 转换Name类型到 有理数类Rational

    Rational(string str){}           // 转换string类型 到有理数类
};

int main()
{
    char ch = 'a';
    string str;
    Name name(str);

    int i = 3;
    Rational ra;

    //以下右边都进行了隐式转换
    ra = i;        // 执行Rational(int numerator = 0,int denominator = 1)转换
    ra = ch;       //执行Rational(int numerator = 0,int denominator = 1)转换
    ra = str;      //执行Rational(string str)转转
    ra = name;     //执行Rational(Name name)转换
}

从以上两个例子可以看到:在单参数构造函数中隐式转换很容易发生。

隐式类型转换运算符

就是 operator 关键字,其后跟一个类型符号。

class Rational
{                                   // 有理数类
public:
    operator double() const           // 转换Rational类成 double类型
    {
    }

    operator string () const            // 转换Rational类成 string类型
    {
    }
};

string str;
Rational ra;
int i;

str = ra;     // 执行operator string ()转换string 运行崩溃
i = 1*ra;     //执行operator double()转换成double型
cout<<ra;     //执行operator double() 转换成double型输出随机浮点数

所以避开类型转换运算符!

隐式转化的消除

隐式类型转换运算符

不提供这种operator转换运算符。使用等同的函数来替代转换运算符;
用asDouble函数代替operator double函数。

double asDouble() const;           //转变 Rational 成double
cout << ra.asDouble();             //相当于提供一个接口

单参数构造函数

使用关键字explicit (这个需要编译器支持!)
编译器会拒绝为了隐式类型转换而调用构造函数。显式类型转换依然合法。

class Name
{                                   // for names of things
public:
    explicit Name(const string &s)  // 转换 string 到  Name
    {

    }
};

int main()
{
    string str;
    Name name(str);

    name = static_cast<Name> (str);//Right 显式转换
    name = str;                    //Error explicit禁止隐式类型转换
}