C++中类类型转换中的转换函数和友元函数
下面为 Stonewt 类重载加法运算符。在讨论 Time 类时指出过,可以使用成员函数或友元函数来重载加法。出于简化的目的,我们假设没有定义operator double()转换函数。)可以使用下面的成员函数实现加法:
Stonewt Stonewt::operator+(const Stonewt & st) const
{
double pds = pounds + st.pounds;
Stonewt sum(pds);
return sum;
}
也可以将加法作为友元函数来实现,如下所示:
Stonewt operator+(const Stonewt & st1, const Stonewt & st2)
{
double pds = st1.pounds + st2.pounds;
Stonewt sum(pds);
return sum;
}
别忘了,可以提供方法定义或友元函数定义,但不能都提供。上面任何一种格式都允许这样做:
Stonewt jennySt(9,12);
Stonewt bennySt(12,8);
Stonewt total;
total = jennySt + bennySt;
另外,如果提供了Stonewt(double)构造函数,则也可以这样做:
Stonewt jennySt(9,12);
double kennyD = 176.0;
Stonewt total;
total = iennySt + kennyD;
但只有友元函数才允许这样做:
Stonewt jennySt(9,12);
double pennyD = 146.0;
Stonewt total;
total = pennyD + jennySt;
为了解其中的原因,将每一种加法都转换为相应的函数调用。首先:
total = jennySt + bennySt;
被转换为:
total = jennySt.operator+(bennySt); // member function
或:
total = operator+(jennySt, bennySt); // friend function
上述两种转换中,实参的类型都和形参匹配。另外,成员函数是通过 Stonewt对象调用的。参见【0voice C++】
其次:
total =jennySt + kennyD;
被转换为:
total =jennySt.operator+(kennyD);//member function
或:
total =operator+(jennySt,kennyD);//friend function
同样,成员函数也是通过 Stonewt对象调用的。这一次,每个调用中都有一个参数(kennyD)是 doublc
类型的,因此将调用Stonewt(double)构造函数,将该参数转换为Stonewt对象。另外,在这种情况下,如果定义了operator double()成员函数,将造成混乱,因为该函数将提供另一种解释方式。编译器不是将 kennyD转换为 double 并执行 Stonewt 加法,而是将jennySt转换为 double 并执行double 加法。过多的转换函数将导致二义性。
最后:
total =pennyD +jennySt;
被转换为:
total =operator+(pennyD,jennySt);//friend function
其中,两个参数都是 double 类型,因此将调用构造函数 Stonewt(double),将它们转换为 Stonewt 对象然而,不能调用成员函数将iennySt和 peenyD相加。将加法语法转换为函数调用将类似于下面这样:
total=pennyD.operator+(jennySt);//not meaningful
这没有意义,因为只有类对象才可以调用成员函数。C++不会试图将pennyD转换为 Stonewt对象。将对成员函数参数进行转换,而不是调用成员函数的对象。
这里的经验是,将加法定义为友元可以让程序更容易适应自动类型转换。原因在于,两个操作数都成为函数参数,因此与函数原型匹配。