尝试学习C ++函数模板。作为其中的一部分,我在下面有这个代码。它工作正常,但我有以下问题: -
1]为什么运营商<<重载功能需要成为朋友吗?如果我删除关键字friend,则会出现编译错误:operator<<参数太多了。
2]为什么运营商<<重载函数需要返回对ostream对象的引用,这也是它的输入参数吗?
3]我对此表示怀疑,但上述两个问题是否与函数模板用于具有重载函数的用户定义类的事实有关?
template <class T>
T Average(T *atArray, int nNumValues)
{
T tSum = 0;
for (int nCount=0; nCount < nNumValues; nCount++)
tSum += atArray[nCount];
tSum /= nNumValues;
return tSum;
}
class Cents
{
private:
int m_nCents;
public:
Cents(int nCents)
: m_nCents(nCents)
{
}
//Why is friend needed below
//Why does it need to return ostream&, why can't it have void return type, as all it is doing is printing the class private member.
friend ostream& operator<< (ostream &out, const Cents &cCents)
{
out << cCents.m_nCents << " cents ";
return out;
}
/*
void operator <<( const Cents &cCents) //did not work - compilation errors
{
cout << cCents.m_nCents << " cents ";
}
*/
void operator+=(Cents cCents)
{
m_nCents += cCents.m_nCents;
}
void operator/=(int nValue)
{
m_nCents /= nValue;
}
};
int main()
{
int anArray[] = { 5, 3, 2, 1, 4 };
cout << Average(anArray, 5) << endl;
double dnArray[] = { 3.12, 3.45, 9.23, 6.34 };
cout << Average(dnArray, 4) << endl;
Cents cArray[] = { Cents(5), Cents(10), Cents(15), Cents(14) };
cout << Average(cArray, 4) << endl;
cin.get();
return 0;
}
答案 0 :(得分:3)
为什么运营商&lt;&lt;重载功能需要成为朋友吗?如果我删除关键字friend,则会出现编译错误:operator&lt;&lt;参数太多了。
<<
改变了流的状态,因此理想情况下它应该被实现为它的左操作数类型的成员。但是,它的左操作数是来自标准库的流,虽然标准库定义的大多数流输出和输入操作符确实被定义为流类的成员,但当您为自己的类型实现输出和输入操作时,无法更改标准库的流类型
这就是为什么您需要为自己的类型实现这些(<<
和>>
)运算符作为非成员函数。由于您需要在运算符定义中访问类对象的私有/受保护成员变量,因此需要将这些重载运算符声明为您类的朋友。
为什么运营商&lt;&lt;重载函数需要返回对ostream对象的引用,ostream对象也是它的输入参数吗?
返回对标准流对象的引用允许您进行对象链接。
您可以拨打电话:
out<<obj1<<obj2;
模板用于具有重载功能的用户定义类?
模板可帮助您实现可以针对不同方式调用的泛型函数和类 数据类型和编译器负责为这些特定数据类型生成代码。所以以上两点没有关系。
强烈建议阅读此常见问题解答条目:
的 Operator overloading 强>
答案 1 :(得分:1)
[1]它需要是朋友,因为它试图访问私有成员变量m_nCents
,只能访问Cents
的成员函数或Cents
的朋友。< / p>
[2]这是重载“流媒体运营商”的标准功能签名。这样就可以连接<<
s:
out << a << b;
相当于
(out << a) << b;
编辑:您似乎希望operator<<
成为该班级的成员。这是不可能的,因为它的第一个操作数是ostream
而不是Cents
。 friend
实际上将其声明为非成员朋友函数。如果你离开friend
关键字,你将它声明为成员函数(因为它在类定义中),但在这种情况下它有太多的参数(签名中的两个,以及隐式{{1}作为第一个参数,它被调用的那个,Cents
指针,如果你愿意的话。)
将this
声明为非成员函数是标准的执行方式,operator<<
或不是{依赖于您需要friend
,或者您以某种方式公开friend
。
答案 2 :(得分:0)
它必须返回一个ostream并将其作为参数,以便您可以将多个调用链接在一起。
例如:
Cents a,b,c;
cout << a << b << c;
它必须是朋友,因为它不是成员函数,无论您在class
代码块中定义了什么。
让我扩展这个概念。以上示例等同于以下内容:
op(op(op(cout,a),b),c);
其中'op'是重载运算符的实际函数名的简写。请注意,它不是在Cents实例上调用的,实际上它没有this
ptr,因为它就像一个独立的函数一样存在于类之外。