在下面的代码中,我举例说明了运算符重载:
#include <iostream>
using namespace std;
template <typename T>
class A
{
public:
A() {};
A( T &obj) {value = obj;};
~A() {};
T value;
template <typename E>
A<T>& operator = (const A<E> &obj)
{
cout<<"equal operator"<<endl;
if(this == &obj)
return *this;
value = obj.value;
return *this;
}
};
int main()
{
int temp;
temp = 3;
A<int> myobjects(temp);
cout<<myobjects.value<<endl;
temp = 7;
A<int> yourobjects(temp);
yourobjects = myobjects;
cout<<yourobjects.value<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我调试这个程序时,我发现主程序没有调用相等的运算符重载函数.但是,如果我按以下方式更改等于运算符:
A<T>& operator = (const A<T> &obj)
{
cout<<"equal operator"<<endl;
if(this == &obj)
return *this;
value = obj.value;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
它会工作.你有什么想法为什么初始功能不起作用?
您的模板版本的赋值运算符不会抑制为您的类生成编译器提供的非模板复制赋值运算符.编译器将使用以下签名隐式声明和定义复制赋值运算符
A<T>& operator =(const A<T>&);
Run Code Online (Sandbox Code Playgroud)
在复制分配的重载解析过程中,编译器提供的版本获胜(因为它更专业).
您的模板版本的赋值运算符仅用于转换赋值.例如,如果在某些时候您想要将A<int>对象分配给A<double>对象,则将使用赋值运算符的模板版本.但是当您分配A<int>给A<int>您的运算符时会被忽略,因为编译器声明的版本是更好的匹配.
当您声明自己的副本分配版本时
A<T>& operator =(const A<T>&);
Run Code Online (Sandbox Code Playgroud)
签名,它会抑制编译器生成的签名.你的版本被使用了.
这意味着如果您想拥有自己的复制赋值运算符以及模板转换赋值运算符,则需要在类中明确实现这两者.
PS作为'@Cheers和hth. - Alf'正确地指出,你的模板版本的赋值运算符在一般情况下甚至都不是有效的.指针this和&obj通常有不同的类型无关.您不能比较不同无关类型的指针.