欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

深入理解C++11:详解转换函数与explicit关键字

最编程 2024-07-27 07:05:02
...

目的:一种类型的对象能不能转换成另一种类型。

1 conversion function

这是转换函数。可以“转出去”,即为把自己定义的类的类型,转换成内置类型(如int)。也可以“转回来”。
Fraction类型是分数,和double类型很相近,因此可以把Fraction类型看做double类型。
操作:用**operator double()**这个函数即可加以转换,表示Fraction可以转换为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);
	}
private:
	int m_numerator;	//分子
	int m_denominator;	//分母
};

Fraction f(3,5);
double d = 4 + f;//调用operator double()将f转为0.6,d即为4.6

注意:没有参数,也不用写返回类型;转换函数一般不会处理内部的值,故通常都有那个const。

2 non-explicit-one-argument ctor

用来“转回来”!
one-argument,即一个实参。由于后面参数den一个有默认值,故只给一个实参就够了。
“+”作用于左边。

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);
double d = 4 + f;//调用non-explicit ctor将4转为Fraction(4,1),然后调用operator+

没有explicit的构造函数,可以作用于operator符号的左手边

注意:
conversion function和non-explicit-one-argument ctor不能并存,应避免二义性,如下情况编译无法通过:

class Fraction
{
public:
    Fraction(int num, int den=1):m_numerator(num), m_denominator(den) { }
    operator double() const					//conversion function 作用在右边,把4转换为Fraction
    {
        return (double) (m_numerator / m_denominator);
    }
    Fraction operator+(const Fraction& f)	//non-explicit-one-argument ctor,将加号左边的Fraction转为double
    {
        return Fraction(......);
    }
private:
    int m_numerator;
    int m_denominator;
};

Fraction f(3, 5);
Fraction d2 = f + 4;//[ERROR]ambiguous 多于一条路可行,发生二义

3 explicit-one-argument ctor

为了避免发生歧义,即避免以上情况,使用关键字explicit。
使用了explicit,让类型不再发生改变,即4不会再变为Fraction的4/1。绝大多数情况,这个关键字只用于构造函数前面。

class Fraction
{
public:
    explicit 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]conersion from 'double' to 'Fraction' requested,右边的4不能变成Fraction,不能加。

4 标准库中转换函数的例子

模板偏特化部分:

template<class Alloc>
class vector<bool, Alloc>
{
public:
    typedef __bit_reference reference;
protected:
    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)); }
...

operator[]函数的返回类型是reference,是__bit_reference类型的别名。下面一段函数看到了__bit_reference类的定义。
reference应该传回bool类型的值,因此用转换函数operator bool()将__bit_reference转换成bool类型值。

推荐阅读