从这周开始,进入了c++下半部分的学习,这周学习的东西相对之前来说比较琐碎,但都是值得注意的地方。
一、转换函数
转换函数是一种特殊类型的类成员函数。它定义了一个由用户定义的转换,以便把一个类对象转换成某种其他的类型。
在类的声明中,通过指定关键字operator,并在其后加上转换的目标类型可以来声明转换函数,一般格式为:
operator type()
转换函数的基本规则:
(1)转换函数只能是成员函数,无返回值,空参数。
(2)不能定义到void的转换,也不允许转换成数组或者函数类型。
(3)转换常定义为const形式,原因是它并不改变数据成员的值。
具体的例子:
class Fraction { public: Fraction(int num, int den) : 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; // 调用operater double将f转换成double
double d = 4 + f;
这一语句首先查找Fraction是否有重载操作符 operator + (double, Fraction) 的函数,由于没有,所以会调用转换函数operator double() const
这里主要是把 f 转换成一个double 值。
non-explicit-one-argument constructor
例子:
class Fraction { 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; // 调用non-explicit ctor将4转换成Fraction(4, 1),然后再调用operator +
构造函数虽然有two parameters(两个形参),但只有one argument,且构造函数前面没有explicit,所以叫做non-explicit-one-argument constructor。
这里主要是通过调用构造函数和通过重载操作符“+”,把4转换成一个Fraction对象。
conversion function vs. non-explicit-one-argument constructor
class Fraction { 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转换成Fraction 也可以将f转换成double,与4相加得到一个double,然后再转换成Fraction
为了使得编译通过,可以将Fraction d2 = f + 4;
改成double d2 = f + 4
explicit-one-argument constructor
class Fraction { 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] convertion from double to Fraction requested
由于在构造函数前面增加了explicit关键字,所以不能将4转换成Fraction类型;也不能先将f转换成double类型,与4相加后再将double转换成Fraction。
explicit这个关键字基本只出现在构造函数前面,意思是需要明确地需要调用这个构造函数才能调用,不存在暗中、自动的转换操作。
二、point-like class
(1)智能指针
关于point-like class 的设计,首先,其内必有一真正的指针,并且为了使得智能指针在使用时像正常指针一样,其设计中必须对操作符 *和->进行重载。