2014-06-05 45 views
2

我正在通过代码...我找到了一个模板类,声明如下。模板和运算符重载

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); } 

我不明白,当上面的操作符被称为... cos当我做...

int main(void) 
{ 
    tType<int> x; 
    x = 5; 
    if (5 == x) 
    { 
     cout << "Both are equal" << endl; 
    } 
    return 0; 
} 

上述操作符不是getti NG叫......和还在工作......我也写了下面的测试,下面的代码片段获取调用代码...

template<class T> 
bool operator==(int x, tType<T>& val) { return (x == val.value); } 

我不知道该给谁打电话*** ** 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; } 

这使您可以比较的最大控制。另一种方法是允许从T的角度隐含构建tType,但隐式构造和转换操作符现在普遍不受欢迎 - 它们可能会导致含糊不清和临时创建的临时对象难以调试。另一个问题的主题....

当你说“上述操作员没有被调用...并仍在工作” - 实际发生的是tType::operator T()(它返回value;)被隐式调用,返回可以比较的int - 作为int - 至5。因此 - 你有一个比较,但不使用自定义operator==。这是找到函数调用的“最佳匹配”的正常结果。

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&

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经由其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()); } 

重要更改:

  1. 添加了一个构造函数,它具有单个值;这允许将Ts转换成tTypes。
  2. 删除赋值运算符采取T S(因为现在我们可以将它们转换为tType秒。
  3. 只能有一个平等的运营商,它有两个const tType<T>& S,这意味着operator==可以处理的T S和tType<T>小号的任意组合(或,甚至更好,任何可转换成任何一种的东西)