class Fraction { public: Fraction(int num,int den=1):m_numerator(num),m_denominator(den) { cout << "构造函数被默默调用了哦!!!" << endl; } ~Fraction(){ cout << "析构函数被默默-调用了哦!!!" << endl; } Fraction operator +(const Fraction& f) { return Fraction (......); } private: double m_numerator; double m_denominator; };
注解:
- 蓝色这种函数相当特别,特别把这一种构造函数叫做non-explcit-one-argument ctor.
- argument代表实参,但后一个参数有初值,所以此时要创建一个Fraction的对象,只要提供一个实参就行了。因为第二个实参有默认值。这样的设计是合理的,因为在数学上,3等于1分之3,分母默认1.
- 这个蓝色背景的函数属于two parameter, one argument.后者的意思是只要一个实参就够了。给两个实参也可以的。
- explicite是个关键字,可以出现在构造函数的前面,现在没有出现,所以就叫做non-explicit-one-argument ctor.
- Fraction d2=f+4; 这一句会让编译器寻找‘+’这个动作,它找到了,就是函数operator+() . +要作用在左边的操作数上,左边的f调用+,但是它发现+的右边的操作数也是一个Fraction(注意,类的成员函数有个隐含的this指针),而实际调用的时候却是f+4,右边的操作数不是Fraction类型的对象。此时编译器会看看能不能把4转换为Fraction类型的对象,如果有4能转换为Fraction,那就是分数+分数,就符合那个成员函数的设计了。因此,现在编译器考虑的是4能不能转换成Fraction,4就是4/1,它发现蓝色区域的代码可以把4转变为分数。所以Fraction d2=f+4; 这一句会首先调用non-explicit ctor 将4转为Fraction(4,1),然后调用operator +()这个函数。
- Fraction d2=f+4; 这句相当于Fraction d2=f(3,5)+f(4,1). (来自网友弹幕)
- 别(内置)的类转变为Fraction,而上一讲是Fraction转变为别(内置)的类。方向正好相反。
#pragma once #include<iostream> using namespace std; class Fraction { public: Fraction(int num,int den=1):m_numerator(num),m_denominator(den) { cout << "构造函数被默默调用了哦!!!" << endl; } operator double() const { return (double)(m_numerator/ m_denominator); } ~Fraction(){ cout << "析构函数被默默-调用了哦!!!" << endl; } Fraction operator +(const Fraction& f) { return Fraction (......); } private: double m_numerator; double m_denominator; };
#include <iostream> using namespace std; #include"conversion_function.h" void main() { Fraction f(3,5); cout << "The fraction f is: "<<f << endl; Fraction d2=f+4; cout << "The fraction d2 is: " << d << endl; system("pause"); }
注解:
- 若有红色和橙色两个函数,编译器遇到Fraction d2=f+4; 时,就不知道该怎么办了。因为不知道是应该调用橙色部分的函数把f转换为double(3/5转变为0.6,0.6+4=4.6,4.6能不能再转为Fraction呢?),还是应该调用粉红色部分把4(double)转换为Fraction.
- 如果一句代码有两条路可以走,则会出现歧义,此时会出现Error错误。
- d2的数据类型改为double 才会ambiguous 把?(网友弹幕)
- double可以默认转换为int(网友弹幕)
#pragma once #include<iostream> using namespace std; class Fraction { public: explicit Fraction(int num,int den=1):m_numerator(num),m_denominator(den) { cout << "构造函数被默默调用了哦!!!" << endl; } operator double() const { return (double)(m_numerator/ m_denominator); }; ~Fraction(){ cout << "析构函数被默默-调用了哦!!!" << endl; } Fraction operator +(const Fraction& f) { return Fraction (3,9); } private: double m_numerator; double m_denominator; };
#include <iostream> using namespace std; #include"conversion_function.h" void main() { Fraction f(3,5); cout << "The fraction f is: "<<f << endl; Fraction d2=f+4; cout << "The fraction d2 is: " << d << endl; system("pause"); }
注解:
- explicit意思是明确的,加上explicit意思就是告诉编译器,我这个构造函数是明确的构造函数,只用于构造对象,不用于类型转换,不要自动把double转换为Fraction哦.
- Fraction d2=f+4; 编译器再遇到这一行的时候,就不会把4转变为4/1了,因为构造函数的前面加了关键字explicit.
- Fraction d2=f+4; 编译器遇到这一句就会去调用+的重载函数了,但重载函数的右操作数类型是Fraction,而4不会被转变为Fraction,所以会出错。报错信息为:[Error] conversion from "double" to 'Fraction' requested.
- 此时为何不把Fraction转变为double?(网友弹幕)
- 这里的问题应该出现在4.6(double)转换为Fraction的时候转换不过去(网友弹幕)