无法组合模板和 class 函数重载
Trouble combining templates and class function overloading
下面的代码工作正常,按预期打印出 50。然而,我不明白的是,为什么不能通过对这段代码稍作改动来编写同一个程序。建议的两行代码被标记为 Bad code 1 和 2。当将它们替换为它们左侧的当前工作代码时(即在 addStuff
和 main
中),我收到以下错误:
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream}' and 'MyClass')|
我期望它工作的方式是:当 addStuff(x,y)
在 main()
的(坏的)cout
行被调用时,它首先计算 x+y
,其行为由 operator+
MyClass 重载成员函数定义。这应该只是 return 一个 MyClass 对象,然后调用 getVar 就没有问题了。
我在这里错过了什么?
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass(){}
MyClass(int a) : priV(a){}
MyClass operator+(MyClass otherMC)
{
MyClass newMC;
newMC.priV = this->priV + otherMC.priV;
return newMC;
}
int getVar(){return priV;}
void setVar(int v){priV=v;}
private:
int priV;
};
template <class gen>
gen addStuff(gen x, gen y)
{
return x+y; //Bad code 1: return (x+y).getVar();
}
int main()
{
MyClass x(20), y(30);
cout << addStuff(x,y).getVar() << endl; //Bad code 2: cout << addStuff(x,y) << endl;
}
您必须修改 addStuff
,使其 return 成为 int
,而不是模板参数 gen
(即 MyClass
):
template <class gen>
int addStuff (gen x, gen y)
{
return (x + y).getVar ();
}
如果你不把gen
改成int
,那么这个函数就可以正常工作,因为构造函数MyClass(int a)
会被显式调用,然后结果会是一个对象输入 MyClass
.
显然编译器会说你不能'cout
'一个MyClass
.
类型的对象
所以我建议你用explicit
标记构造函数:
另外你的代码没有编译因为没有默认构造函数,所以添加一个,或者简单地用默认值标记参数:
explicit MyClass (int a = 0) : priV (a) {}
编辑:
如果你不想在改变成员的类型时改变函数的return类型,你可以使用decltype,使代码更通用:
template <class gen>
decltype (auto) addStuff (gen x, gen y) //Or decltype (declval<gen> ().getVar ())
{
return (x + y).getVar ();
}
问题出在 addStuff
函数中,它 returns MyClass 对象,由 int 变量构造。您需要修改此函数以使用 "bad code"
template <class gen>
int addStuff(gen x, gen y)
{
return (x+y).getVar();
}
或者为MyClass写一个ostream操作符。为此,您需要修改 getVar
方法,包括友元声明并实现它
int getVar() const { return priV; }
friend std::ostream& operator<< (std::ostream &out, const MyClass& m);
std::ostream& operator<< (std::ostream& out, const MyClass& m) {
out << m.getVar();
return out;
}
这样你就不需要修改addStuff
函数了。
旁注,你的代码没有为我编译,因为 MyClass 中没有默认构造函数,必须像这样修改构造函数
MyClass(int a = 0) : priV(a) {}
您对第 1 行中应该发生的事情的解释 return (x+y).getVar();
是正确的。重载的 operator+
将在参数 x 和 y 上被调用,而 getVar()
将在 operator+
的结果上被调用。当 x 和 y 是 MyClass 类型时,operator+ 调用 returns 一个 MyClass 类型的对象,因此对 getVar()
的调用有效。
但是,getVar()
return 是一个整数。您的函数 addStuff
被指定为 return gen
,这是与参数 x 和 y 匹配的相同模板参数。这意味着当 x 和 y 是 MyClass 时,addStuff
函数必须 return MyClass.
因此,当您将 addStuff(x,y)
放入 cout
语句中时,addStuff
的 return 类型被推断为 MyClass。这就是使您的编译器产生 "there is no operator<< for type MyClass."
错误的原因
如果你想addStuff
到returngetVar()
的结果,你应该将它声明为returnint
,而不是gen
.
下面的代码工作正常,按预期打印出 50。然而,我不明白的是,为什么不能通过对这段代码稍作改动来编写同一个程序。建议的两行代码被标记为 Bad code 1 和 2。当将它们替换为它们左侧的当前工作代码时(即在 addStuff
和 main
中),我收到以下错误:
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream}' and 'MyClass')|
我期望它工作的方式是:当 addStuff(x,y)
在 main()
的(坏的)cout
行被调用时,它首先计算 x+y
,其行为由 operator+
MyClass 重载成员函数定义。这应该只是 return 一个 MyClass 对象,然后调用 getVar 就没有问题了。
我在这里错过了什么?
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass(){}
MyClass(int a) : priV(a){}
MyClass operator+(MyClass otherMC)
{
MyClass newMC;
newMC.priV = this->priV + otherMC.priV;
return newMC;
}
int getVar(){return priV;}
void setVar(int v){priV=v;}
private:
int priV;
};
template <class gen>
gen addStuff(gen x, gen y)
{
return x+y; //Bad code 1: return (x+y).getVar();
}
int main()
{
MyClass x(20), y(30);
cout << addStuff(x,y).getVar() << endl; //Bad code 2: cout << addStuff(x,y) << endl;
}
您必须修改 addStuff
,使其 return 成为 int
,而不是模板参数 gen
(即 MyClass
):
template <class gen>
int addStuff (gen x, gen y)
{
return (x + y).getVar ();
}
如果你不把gen
改成int
,那么这个函数就可以正常工作,因为构造函数MyClass(int a)
会被显式调用,然后结果会是一个对象输入 MyClass
.
显然编译器会说你不能'cout
'一个MyClass
.
所以我建议你用explicit
标记构造函数:
另外你的代码没有编译因为没有默认构造函数,所以添加一个,或者简单地用默认值标记参数:
explicit MyClass (int a = 0) : priV (a) {}
编辑: 如果你不想在改变成员的类型时改变函数的return类型,你可以使用decltype,使代码更通用:
template <class gen>
decltype (auto) addStuff (gen x, gen y) //Or decltype (declval<gen> ().getVar ())
{
return (x + y).getVar ();
}
问题出在 addStuff
函数中,它 returns MyClass 对象,由 int 变量构造。您需要修改此函数以使用 "bad code"
template <class gen>
int addStuff(gen x, gen y)
{
return (x+y).getVar();
}
或者为MyClass写一个ostream操作符。为此,您需要修改 getVar
方法,包括友元声明并实现它
int getVar() const { return priV; }
friend std::ostream& operator<< (std::ostream &out, const MyClass& m);
std::ostream& operator<< (std::ostream& out, const MyClass& m) {
out << m.getVar();
return out;
}
这样你就不需要修改addStuff
函数了。
旁注,你的代码没有为我编译,因为 MyClass 中没有默认构造函数,必须像这样修改构造函数
MyClass(int a = 0) : priV(a) {}
您对第 1 行中应该发生的事情的解释 return (x+y).getVar();
是正确的。重载的 operator+
将在参数 x 和 y 上被调用,而 getVar()
将在 operator+
的结果上被调用。当 x 和 y 是 MyClass 类型时,operator+ 调用 returns 一个 MyClass 类型的对象,因此对 getVar()
的调用有效。
但是,getVar()
return 是一个整数。您的函数 addStuff
被指定为 return gen
,这是与参数 x 和 y 匹配的相同模板参数。这意味着当 x 和 y 是 MyClass 时,addStuff
函数必须 return MyClass.
因此,当您将 addStuff(x,y)
放入 cout
语句中时,addStuff
的 return 类型被推断为 MyClass。这就是使您的编译器产生 "there is no operator<< for type MyClass."
如果你想addStuff
到returngetVar()
的结果,你应该将它声明为returnint
,而不是gen
.