首先是个这样的小数的例子,没加explicit看看是什么情况:
类:
//
// Created by 浅笑 on 2022/11/28.
//
#ifndef CLION_PJ_FRACTION_H
#define CLION_PJ_FRACTION_H
class Fraction{
public:
Fraction(int num,int den=1):m_numerator(num),m_denominator(den){}
Fraction operator+(const Fraction& f);
operator double() const {
return (double)m_numerator / m_denominator;
}
private:
int m_numerator;
int m_denominator;
friend int gcd(const Fraction& f1, const Fraction f2);
};
int gcd(const Fraction& f1, const Fraction f2){
int m=f1.m_numerator*f2.m_denominator+f1.m_denominator*f2.m_numerator;
int n=f1.m_denominator*f2.m_denominator;
int r;
while (n!=0){
r=m%n;
m=n;
n=r;
}
// std::cout<<m<<std::endl;
return m;
}
Fraction Fraction::operator+(const Fraction &f) {
int g= gcd(*this,f);
int m_num=(m_numerator*f.m_denominator+m_denominator*f.m_numerator)/g;
int m_de=(f.m_denominator*m_denominator)/g;
// std::cout<<m_numerator*f.m_denominator+m_denominator*f.m_numerator<<std::endl;
// std::cout<<f.m_denominator*m_denominator<<std::endl;
return Fraction(m_num,m_de);
}
#endif //CLION_PJ_FRACTION_H
测试如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<string>
#include"Fraction.h"
using namespace std;
int main()
{
Fraction f(3,5);
Fraction d2=f+4.0;
cout<<(double)d2;
return 0;
}
之后就炸了:
这里说噢,有二义性:
1.这里的f+4可以用Fraction的+运算符的重载,而这里的操作就是先把4.0由构造函数转变成Fraction类,再用重载的操作符计算。
2.也可以用double的+运算符,操作就是先直接把Fraction用double操作符转过去,再用+号计算,那么我们到底用哪个呢?不知道。
然后我们给类的构造函数加上explicit再测试一次:
explicit Fraction(int num,int den=1):m_numerator(num),m_denominator(den){}
又炸了,不过这次他说的是没有给可见的从double到Fraction的转换,显式的构造函数不是一个候选项,说明啥,我们在加了explicit之后,编译器式不会隐式调用构造函数的!所以这里是两个double相加,那么最后要从double到Fraction,我们就要显式地加上一个构造的函数。
将测试修改如下:
int main()
{
Fraction f(3,5);
cout<<(double)f<<endl;
double ans=f+4.0;
cout<<ans<<endl;
Fraction d2=f+Fraction(4.0);
cout<<(double)d2<<endl;
return 0;
}
结果如下所示:
那为啥不Fraction(f+4.0)呢,由于两个数据是int的,所以在初始化的时候把小数给抹去了sos。不过关键还是理解explicit辣!