為什么需要 explicit
想要明白 explicit 就必須得搞清楚「轉換函數」這一個基本概念。
什么是轉換函數
轉換函數,就是一個類的成員函數,當編譯器發現一個類需要轉換成另外一個類的時候,會主動找到對應的轉換函數。看下面這個例子:
#include <bits/stdc++.h>
using namespace std;
class Fraction {
private:
int m_numerator; // 分子
int m_denominator; // 分母
public:
Fraction(int num, int den=1): m_numerator(num), m_denominator(den){}
operator double() const {
return double(m_numerator) / m_denominator;
}
};
int main() {
Fraction f(3, 5);
double d = 4 + f;
cout << d << '\n';
return 0;
}
一個新問題——如果有多條轉換路徑會發生什么?
看下面這個例子:
#include <bits/stdc++.h>
using namespace std;
class Fraction {
private:
int m_numerator; // 分子
int m_denominator; // 分母
public:
Fraction(int num, int den=1): m_numerator(num), m_denominator(den){}
Fraction operator+(const Fraction& f) const {
int an = m_numerator, ad = m_denominator;
int bn = f.m_numerator, bd = f.m_denominator;
// an / ad + bn / bd = (an*bd + bn*ad) / ad * bd
int nn = an*bd + bn*ad, nd = ad * bd;
// 沒有除以最小公倍數
return Fraction(nn, nd);
}
operator double() const {
return double(m_numerator) / m_denominator;
}
};
int main() {
Fraction f(3, 5);
Fraction d = f + 4;
cout << d << '\n';
return 0;
}
這樣會報錯,有兩種轉換思路:
- 4 轉換成 Fraction 兩者相加
- Fraction f 轉換成 double 加上 4 轉換成 int,調用 Fraction 的構造函數。
但是加上 explicit 就會不一樣
explicit 的作用
主動告訴編譯器,只有主動調用構造函數的時候才能使用構造函數。
#include <bits/stdc++.h>
using namespace std;
class Fraction {
private:
int m_numerator; // 分子
int m_denominator; // 分母
public:
explicit Fraction(int num, int den=1): m_numerator(num), m_denominator(den){}
Fraction operator+(const Fraction& f) const {
int an = m_numerator, ad = m_denominator;
int bn = f.m_numerator, bd = f.m_denominator;
// an / ad + bn / bd = (an*bd + bn*ad) / ad * bd
int nn = an*bd + bn*ad, nd = ad * bd;
// 沒有除以最小公倍數
return Fraction(nn, nd);
}
operator double() const {
return double(m_numerator) / m_denominator;
}
};
int main() {
Fraction f(3, 5);
Fraction d = f + 4;
cout << d << '\n';
return 0;
}
這樣還是會報錯,因為只有一條路徑:
- f 變成 double,4 + double 還是 double。但是 double 不能轉換成 Fraction。