以下是一段代码,假如没有什么不寻常的原因,实在看不出什么对象:
class UPInt { // unlimited precision
public: // integers 类
UPInt();
UPInt(int value);
…
};
//有关为什么返回值是const的表明,拜见Effective C++ 条款21
const UPInt operator+(const UPInt& lhs, const UPInt& rhs);
UPInt upi1, upi2;
…
UPInt upi3 = upi1 + upi2;
这里还看不出什么令人惊奇的对象。upi1 和upi2都是UPInt工具,所以它们之间相加就会挪用UPInts的operator函数。
此刻思量下面这些语句:
upi3 = upi1 + 10;
upi3 = 10 + upi2;
这些语句也可以或许乐成运行。要领是通过成立姑且工具把整形数10转换为UPInts(拜见条款19)。
让编译器完成这种范例转换是确实是很利便,可是成立姑且工具举办范例转换事情是有开销的,而我们不想包袱这种开销。就象大大都人只想从当局哪里受益而不想为此支付一样,大大都C++措施员但愿举办没有姑且工具开销的隐式范例转换。可是在计较规模里产生不了赤字现象,我们如何能这么做呢?
让我们回退一步,认识到我们的目标不是真的要举办范例转换,而是用UPint和int做为参数挪用operator。隐式范例转换只是用来到达目标的手段,可是我们不要夹杂手段与目标。尚有一种要领可以乐成举办operator的殽杂范例挪用,它将消除隐式范例转换的需要。假如我们想要把UPInt和int工具相加,通过声明如下几个函数到达这个目标,每一个函数有差异的参数范例集。
const UPInt operator+(const UPInt& lhs, // add UPInt
const UPInt& rhs); // and UPInt
const UPInt operator+(const UPInt& lhs, // add UPInt
int rhs); // and int
const UPInt operator+(int lhs, // add int and
const UPInt& rhs); // UPInt
UPInt upi1, upi2;
…
UPInt upi3 = upi1 + upi2; // 正确,没有由upi1 或 upi2
// 生成的姑且工具
upi3 = upi1 + 10; // 正确, 没有由upi1 or 10
// 生成的姑且工具
upi3 = 10 + upi2; //正确, 没有由10 or upi2
//生成的姑且工具。
一旦你开始用函数重载来消除范例转换,你就有大概这样声明函数,把本身陷入危险之中:
const UPInt operator+(int lhs, int rhs); // 错误!
这个想法是合情公道的。对付UPInt和int范例,我们想要用所有大概的组合来重载operator函数。上面只给出了三种重载函数,独一遗漏的是带有两个int参数的operator,所以我们想把它加上。
有原理么?在C++中有一条法则是每一个重载的operator必需带有一个用户界说范例(user-defined type)的参数。int不是用户界说范例,所以我们不能重载operator成为仅带有此范例参数的函数。(假如没有这条法则,措施员将能改变预界说的操纵,这样做必定把措施引入杂乱的田地。好比诡计重载上述的operator,将会改变int范例相加的寄义。)
操作重载制止姑且工具的要领不可是用在operator函数上。好比在大大都措施中,你想答允在所有能利用string工具的处所,也一样可以利用char*,反之亦然。同样假如你正在利用numerical(数字)类,譬喻complex(拜见条款35),你想让int和double这样的范例可以利用在numerical工具的任那里所。因此任何带有string、char*、complex参数的函数可以回收重载方法来消除范例转换。
不外,必需服膺80-20法则(拜见条款16)。没有须要实现大量的重载函数,除非你有来由确信措施利用重载函数今后其整体效率会有显著的提高。