这是正确的,您的operator==
未被调用的原因是因为缺少const
标识符。在这种情况下,文字5
无法作为变量参考传递给参数T& val
。但是,这不是完整的故事。
正如您所指出的那样,即使函数未被调用,代码仍然会编译并运行。
您的代码仍然工作的原因是由于conversion operator:operator T(){ return value; }
。
转换运算符允许从一种类型到另一种类型的隐式转换。例如:
struct Number {
Number(int x) : value(x) { }
operator int() { return value; }
private:
int value;
};
int main() {
Number n(5);
int x = n; // 5 -- operator int() at work
int y = n + x; // 10 -- operator int() at work
Number z = x + y; // 15 -- Number(int) at work
cout << x <<" "<< y <<" "<< z << endl;
return 0;
}
这里,operator int()
允许n
到转换成int
用于分配给x
和要转换为int
用于添加与x
(所得int
然后分配给y
),而一元构造Number(int)
允许x + y
的结果转换回Number
。
在代码中,5 == x
仍然编译因为tType<int>
x
经由其operator int()
成员函数转换为int
,然后将该所得的int
抵靠字面5
比较。
但是,这可能不是一个非常好的类设计。例如,为了比较两个tType<T>
s,其中一个需要投入T
。
template <class T>
bool operator==(const T& val, const tType<T>& tval) {
cout << "operator==(const T& val, const tType<T>& tval) was called." << endl;
return(val == tval.value);
}
//...
cout << (tType<int>() == tType<int>()) << endl; // calls operator==(const T&, const tType<T>&)
你宁愿有两个tType<T>
秒的operator==
。
另一个甚至更大的问题是,这是不是对称的:
cout << (x1 == 5) << endl; // calls operator==(int,int) (the built-in function)
哎呀!
要解决所有这些问题,有一个非常简单的设计解决方案。这是从斯科特迈耶斯的书Effective C++ Third Edition
(一本惊人的书)。
不是转换回T
与转换运算符,类应该包括一个隐含的一元构造函数T
的转换高达tType<T>
s,而应该准确地申报一个operator==
为tType<T>
S:
template <class T>
class tType
{
public:
tType<T>(const T &val) : value(val) { } // unary non-explicit constructor
tType<T> operator=(const tType<T> &val){ value = val.value; return *this; } // only need one
T val() { return value; }
private:
T value; // Note also value is private (encapsulation)
};
template<class T>
bool operator==(const tType<T>& a, const tType<T>& b) { return (a.val() == b.val()); }
重要更改:
- 添加了一个构造函数,它具有单个值;这允许将
T
s转换成tType
s。
- 删除赋值运算符采取
T
S(因为现在我们可以将它们转换为tType
秒。
- 只能有一个平等的运营商,它有两个
const tType<T>&
S,这意味着operator==
可以处理的T
S和tType<T>
小号的任意组合(或,甚至更好,任何可转换成任何一种的东西)