有下面的代码,为什么第一次分配不调用模板operator=的Foo,但第二个呢?这里有什么?即使用户定义的模板存在,是否有编译器生成的第一个赋值?
#include <iostream>
using namespace std;
struct UberFoo { };
struct Foo : public UberFoo
{
template<typename T> void operator=(const T& v) { cout << "const T&" << endl; Set(v); }
template<typename T> void operator=(T& v) { cout << "T&" << endl; return Set(v); }
virtual void Set(const Foo&) { cout << "Foo::Set(const Foo&)" << endl; }
virtual void Set(const UberFoo&) { cout << "Foo::Set(const UberFoo&)" << endl; }
};
struct Bar : public Foo
{
virtual void Set(const Foo&) { cout << "Bar::Set(const Foo&)" << endl; }
virtual void Set(const UberFoo&) { cout << "Bar::Set(const UberFoo&)" << endl; }
};
int main()
{
Bar a, b;
Foo & pa = a;
const Foo& rb = b;
const UberFoo & urb = b;
cout << "First" << endl;
pa = rb;
cout << endl << "Second" << endl;
pa = urb;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器仍然生成第一个赋值所绑定的非模板化 operator=.在第二个赋值中,模板化operator=是一个更好的候选者(因为它不涉及强制转换),因此选择一个.
您可以通过在代码中添加以下内容来查看:
Foo& operator=(const Foo&) = delete;
Run Code Online (Sandbox Code Playgroud)
或强制正确的模板调用:
pa.operator=<Foo>(b);
Run Code Online (Sandbox Code Playgroud)
标准说(强调我的):
12.8复制和移动类对象,§12.8/ 17,第271页:
用户声明的复制赋值运算符X :: operator =是类X 的非静态非模板成员函数,其中只有一个参数类型为X,X&,const X&,volatile X&或const volatile X&
§12.8/ 18,同页:
如果类定义未显式声明复制赋值运算符,则会隐式声明一个.