模板和运算符重载

时间:2014-06-05 04:42:41

标签: c++ operator-overloading

我正在浏览代码...我找到了一个模板类,声明如下所示。

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 *****

3 个答案:

答案 0 :(得分:3)

没有调用operator==的原因是因为缺少const标识符。在这种情况下,文字5无法作为参数T& val变量引用传递。但是,这并非完整的故事。

正如您所指出的,即使未调用该函数,代码仍会编译并运行。

您的代码仍然有效的原因是conversion operatoroperator 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>

重要的变化:

  1. 添加了一个带有单个值的构造函数;这允许将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。
  2. 删除了tType s的赋值运算符(因为现在我们可以将它们转换为T s。
  3. 只有一个相等运算符,它需要两个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&,因此未调用您的函数。