我正在浏览代码...我找到了一个模板类,声明如下所示。
template <class T>
class tType
{
public:
T value;
T operator=(T val){ value = val; return value; }
tType<T> operator=(tType<T> &val){ value = val.value; return *this; }
operator T(){ return value; }
};
我还发现运算符超载如下...
****** ****** 1
template <class T>
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); }
我不明白何时上述操作员被调用...当我做的时候......
int main(void)
{
tType<int> x;
x = 5;
if (5 == x)
{
cout << "Both are equal" << endl;
}
return 0;
}
上面说的运算符没有被调用......并且仍在工作......我还在下面编写了测试代码,下面的代码片段被调用...
template<class T>
bool operator==(int x, tType<T>& val) { return (x == val.value); }
我不知道该打电话给谁 ***** 1 *****
答案 0 :(得分:3)
没有调用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
通过其int
成员函数转换为operator int()
,然后生成int
{1}}与文字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>&)
。
operator==
您希望有两个tType<T>
的{{1}}。
另一个更大的问题是这不对称:
cout << (x1 == 5) << endl; // calls operator==(int,int) (the built-in function)
糟糕!
为了解决所有这些问题,有一个非常简单的设计解决方案。这取自Scott Meyers的书Effective C++ Third Edition
(一本惊人的书)。
除了使用转化运算符转换回T
,该类应该包含一个隐式一元构造函数,以将T
转换为tType<T>
,并且应该只声明一个operator==
的{{1}}:
tType<T>
重要的变化:
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
s,这意味着const tType<T>&
可以处理operator==
和T
的任意组合(或者更好的是,可以转换为其中任何一种)。答案 1 :(得分:2)
==
运算符尝试绑定对参数的非const
引用 - 像“5”这样的值不适合...参数应为const
:
template <class T>
bool operator==(const T& val, const tType<T>& tval) { return val == tval.value; }
因为这仍然只支持例如5 == my_tType
而非my_tType == 5
,您可能还想提供......
template <class T>
bool operator==(const tType<T>& tval, const T& val) { return val == tval.value; }
...以及my_tType1 == my_tType2
...
template <class T>
bool operator==(const tType<T>& tval1, const tType<T>& tval2) {
return tval1.value == tval2.value; }
这使您可以最大程度地控制比较。另一种方法是允许从tType
参数隐式构造T
,但现在通常不鼓励隐式构造和转换运算符 - 它们可能导致模糊和偶然创建临时变量,这可能很难调试。另一个问题的话题......
当你说“上面说的操作员没有被调用......并且仍在工作”时 - 实际发生的是tType::operator T()
(返回value;
)被隐式调用,返回int
可以与int
- 5
进行比较。因此 - 您进行了比较,但没有使用自定义operator==
。这是找到函数调用的“最佳匹配”的正常结果。
答案 2 :(得分:1)
更改功能
template <class T>
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); }
到
template <class T>
bool operator==(T const& val, tType<T> const& tval) { return(val == tval.value); }
或
template <class T>
bool operator==(T val, tType<T> tval) { return(val == tval.value); }
由于5
无法转换为int&
,因此未调用您的函数。