转换函数笔记2----C++学习之路

来源:互联网 发布:windows ant下载 编辑:程序博客网 时间:2024/05/16 17:54

  1.non-explicit-one-argument ctor

one-argument的意思就是,只要一个实参就够了,但是你要给两个也行。

代码例子:

class Fraction {public:    Fraction(int num, int den=1)        : m_numerator(num),m_denominator(den){}    Fraction operator+(const Fraction& f){ return Fraction(....); }private:    int m_numerator;    int m_denominator;};
测试用例:

Fraction f(3,5);Fraction d2 = f + 4;
当第二个语句使用f+4的时候,编译器会自动去寻找是否有operator+这个函数,找到了我们发现,这条语句:
Fraction operator+(const Fraction& f){ return Fraction(....); }
+号左边十个Fraction,右边也是Fraction,设计成分数+分数。但是实际上却是f+4,那么编译器就会去考虑4是否

能够转换成Fraction。编译器发现这个语句:

Fraction(int num, int den=1)        : m_numerator(num),m_denominator(den){}
那么4就转换成了4/1,那么语句f+4就通过了编译器。

整个过程就是先调用non-explicit ctor转换为Fraction,然后调用operator+。

  2.但是假如与之前的operator double()并存的话。

代码:

class Fraction{public :    Fraction (int num, int den=1)        :m_numerator(num),m_denominator(den){}    operator double() const{ return (double)( m_numerator/m_denominator);}    Fraction operator+(const Fraction& f){ return Fraction(......); }private:    int m_numerator;    int m_denominator;};
测试用例:

Fraction f(3,5);Fraction d2=f+4;  //[Error] ambiguous
这样看起来,先将4转换成4/1,与f相加得到一个Fraction,看似行得通。

但是看operator double(),将f转换为0.6,加上4得到4.6,那么4.6是否能转换为Fraction?

这样的话,编译器就会引起歧义,就会报错。

当然,这个代码引起的问题和之前的转换函数的笔记中的代码是一样的,但是在上一个笔记中使用者使用的是

double d=f+4;

所以得出结论,类内的设计以及是否会出现歧义,需要更多地去考虑使用者是如何使用的。

  3.explicit-one-argument ctor

这个的explicit的意思是明白的明确的,这告诉编译器来,我这就是个明确的构造函数,你不能让4编程4/1,只能用来当作构造函数。

代码:

class Fraction{public :    explict Fraction (int num, int den=1)        :m_numerator(num),m_denominator(den){}    operator double() const{ return (double)( m_numerator/m_denominator);}    Fraction operator+(const Fraction& f){ return Fraction(......); }private:    int m_numerator;    int m_denominator;};
测试用例:

Fraction f(3,5);Fraction d2=f+4;  //[Error]
这个时候这个加法就是失败的,因为找到operator+的时候,4无法转换为4/1,因为explict,所以4无法转换,所以报错

这个explict百分90都用在构造函数,另外就使用在模板的一个很小的部分。

  4.回到转换函数,标准库中使用到的转换函数。

代码例子:

template <class Alloc>class vector<bool,Alloc>{public:    typedef __bit_reference reference;pretected:    reference operator[](size_type n) { return *(begin()+difference_type(n)); }....};
struct __bit_reference{    unsigned int* p;    unsigned int mask;    ...public:    operator bool() const { return !(!(*p & mask)) }    ...}
第一段代码中,vector的语法是模板的偏特化,从里面有个函数是对[]的重载。

它传回的是reference,可以看得出,这个代码传回的是一个bool值,但是传回的是reference。

这种设计方式称为代理。

那么拿reference来代表一个bool值,就需要把reference转换成一个bool,所以在__bit_reference中有一个转换函数。








原创粉丝点击