避免已知类型向自定义类型隐式转换
explicit关键字加在构造函数前面,可以声明此函数应当被显式调用,而不是在隐式类型转换时被隐式调用。
#include <iostream>
using namespace std;
struct Rational1 {
Rational1(int n=0, int d=1): num(n), den(d) {
cout << __func__ << "(" << num << "/" << den << ")" << endl;
}
int num;
int den;
};
struct Rational2 {
explicit Rational2(int n=0, int d=1): num(n), den(d) {
cout << __func__ << "(" << num << "/" << den << ")" << endl;
}
int num;
int den;
};
void Display1(Rational1 ra) {
cout << "Numerator: " << ra.num << " Denominator: " << ra.den << endl;
}
void Display2(Rational2 ra) {
cout << "Numerator: " << ra.num << " Denominator: " << ra.den << endl;
}
int main() {
Rational1 r1_1 = 11; // OK
Rational1 r1_2(12); // OK
Rational2 r2_1 = 21; // error: conversion from ‘int’ to non-scalar type ‘Rational2’ requested
Rational1 r2_2(22); // OK
Display1(1); // OK
Display2(2); // 隐式构造 error: could not convert ‘2’ from ‘int’ to ‘Rational2’
Display2(Rational2(2)); // 显式构造 OK
return 0;
}
避免自定义类型向已知类型隐式转换
上一小节的例子可以避免已知类型(int)向自定义类型(Rational2)的隐式转换,但没对自定义类型向已知类型转换进行限制。
explicit关键字加在类型转换操作符重载前面,可以做到以上限制。
留意下类型转换操作符的写法,operator 类型() {},比如operator bool() {},这里的bool不是返回值类型,而是与括号连用组成强制类型转换符。
#include <iostream>
using namespace std;
class ConvertTo {};
class Convertable {
public:
explicit operator ConvertTo() const {
return ConvertTo();
}
};
void Func(ConvertTo ct) {}
void test() {
Convertable c;
ConvertTo ct(c); // 直接初始化 OK
ConvertTo ct2 = c; // 拷贝构造时隐式类型转换 error: conversion from ‘Convertable’ to non-scalar type ‘ConvertTo’ requested
ConvertTo ct3 = static_cast<ConvertTo>(c); // 显式强制类型转换 OK
Func(c); // 传参时隐式类型转换 error: could not convert ‘c’ from ‘Convertable’ to ‘ConvertTo’
}
小结
explicit不是禁止从源类型到目标类型的转换,而是限定了所修饰函数必须显式调用,如果所修时函数是构造函数和类型转换操作符,达成了显示类型转换这一效果。
网友评论