non-explicite-one-argumen-constructor

 

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;
};

 

注解:

  1. 蓝色这种函数相当特别,特别把这一种构造函数叫做non-explcit-one-argument ctor. 
  2. argument代表实参,但后一个参数有初值,所以此时要创建一个Fraction的对象,只要提供一个实参就行了。因为第二个实参有默认值。这样的设计是合理的,因为在数学上,3等于1分之3,分母默认1.
  3. 这个蓝色背景的函数属于two parameter, one argument.后者的意思是只要一个实参就够了。给两个实参也可以的。
  4. explicite是个关键字,可以出现在构造函数的前面,现在没有出现,所以就叫做non-explicit-one-argument ctor.
  5. 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 +()这个函数。
  6. Fraction d2=f+4; 这句相当于Fraction d2=f(3,5)+f(4,1). (来自网友弹幕)
  7. 别(内置)的类转变为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");
}

 

注解:

  1. 若有红色和橙色两个函数,编译器遇到Fraction d2=f+4; 时,就不知道该怎么办了。因为不知道是应该调用橙色部分的函数把f转换为double(3/5转变为0.6,0.6+4=4.6,4.6能不能再转为Fraction呢?),还是应该调用粉红色部分把4(double)转换为Fraction.
  2. 如果一句代码有两条路可以走,则会出现歧义,此时会出现Error错误。
  3. d2的数据类型改为double 才会ambiguous 把?(网友弹幕)
  4. 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");
}

 注解:

  1. explicit意思是明确的,加上explicit意思就是告诉编译器,我这个构造函数是明确的构造函数,只用于构造对象,不用于类型转换,不要自动把double转换为Fraction哦.
  2. Fraction d2=f+4; 编译器再遇到这一行的时候,就不会把4转变为4/1了,因为构造函数的前面加了关键字explicit.
  3. Fraction d2=f+4; 编译器遇到这一句就会去调用+的重载函数了,但重载函数的右操作数类型是Fraction,而4不会被转变为Fraction,所以会出错。报错信息为:[Error] conversion from "double" to 'Fraction' requested.
  4. 此时为何不把Fraction转变为double?(网友弹幕)
  5. 这里的问题应该出现在4.6(double)转换为Fraction的时候转换不过去(网友弹幕)

 

posted on 2020-08-16 19:47  一杯明月  阅读(299)  评论(0编辑  收藏  举报