杂货边角(19):explicit显式类型转换限定符号

#include <iostream>

using namespace std;

struct Rational_1 {
    Rational_1(int n=0, int d=1) : num(n), den(d) {
        cout << __func__ << "(" << num << "/" << den << ")" << endl;
    }
    int num;  //Numerator被除数
    int den;  //Denominator除数
};
struct Rational_2 {
    explicit Rational_2(int n=0, int d=1) : num(n), den(d) {
        //加了explicit关键字,代表该构造函数不能被隐式调用,必须显式调用才能运行
        cout << __func__ << "(" << num << "/" << den << ")" << endl;
    }
    int num;  //Numerator被除数
    int den;  //Denominator除数
};

void Display1(Rational_1 ra){
    cout << "Numerator: " << ra.num << " Denominator: " << ra.den << endl;
}

void Display2(Rational_2 ra){
    cout << "Numerator: " << ra.num << " Denominator: " << ra.den << endl;
}

template <typename T>
class Ptr {
public:
    Ptr(T* p) : _p(p) {}

    //定义一个从Ptr类型转换成bool类型的函数
    explicit operator bool() const {
        if (_p != 0)
            return true;
        else
            return false;
    }
private:
    T* _p;
};
/*************************************************************************
**1. explicit 关键字修饰函数,将会禁止函数被隐式调用
**  有些情况下,函数的隐式调用会导致意想不到的问题出现,
**  经常出现问题的场景有:拷贝构造函数的隐式传递调用 和 非显式的类型转换

*************************************************************************/
class ConvertTo {
public:
    ConvertTo() {}
    //ConvertTo( const ConvertTo & ) {}
};

class Convertable {
public:
    explicit operator ConvertTo () const { return ConvertTo(); } //定义Convertable类型向ConvertTo类型的转换函数
};

void Func(ConvertTo ct) {}


int main()
{
    Rational_1 r1_1 = 11;  //该表达式理应是调用拷贝赋值函数,但是因为r1_1并无初始化,所以将隐式调用带参构造函数
    Rational_1 r1_2(12);   //显式调用带参构造函数

    //Rational_2 r2_1 = 21;  //error: conversion from 'int' to non-scalar type 'Rational_2' requested
    Rational_2 r2_2(22);   //显式调用带参构造函数,可以编译通过

    Display1(1);  //参数传递,将隐式调用构造函数
    //Display2(2);  //无法通过编译,could not convert '2' from 'int' to 'Rational_2'
    Display2(Rational_2(2)); //显式调用构造函数传递临时对象

    int a;
    Ptr<int> p(&a);
    if (p)
        cout << "valid pointer." <<endl; //valid pointer
    else
        cout << "invalid pointer." << endl;

    Ptr<double> pd(0);
    //cout << p+pd << endl; //如果不加explicit修饰Ptr类中的转换函数,则该表达式将会隐式调用
        //该转换函数,但是指针量之间的相加并无意义,但是因为转换函数的定义,该表达式将被编译通过
        //所以应该给转换函数加上explicit,以避免可能存在不当使用并且难以察觉
        //加上explicit修饰转换函数后,则除了在bool量应该出现的位置,是不会调用该转换函数的
        //所以编译器将报错:error: no match for 'operator+' (operand types are 'Ptr<int>' and 'Ptr<double>'

    Convertable c;
    ConvertTo ct(c);  //直接初始化,pass
    //ConvertTo ct2 = c;  //error: conversion from 'Convertable' to non-scalar type 'ConvertTo' requested
    ct = static_cast<ConvertTo>(c); //强制类型转化,通过
    Func(static_cast<ConvertTo>(c));  //could not convert 'c' from 'Convertable' to 'ConvertTo'

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值