关于重载运算符<<的问题
Question about the overloaded operator <<
尝试研究C++函数模板。作为其中的一部分,我有下面的代码。它运行良好,但我有以下问题:-
1] 为什么运算符<lt;重载函数需要成为朋友吗?如果我删除关键字friend,它会给出编译错误:operator<lt;参数太多。
2] 为什么运算符<lt;重载函数是否需要返回对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;
}
为什么运算符<lt;重载函数需要成为朋友吗?如果我删除关键字friend,它会给出编译错误:operator<lt;参数太多。
<<
会更改流的状态,因此理想情况下,它应该实现为其左操作数类型的成员。然而,它的左操作数是来自标准库的流,虽然标准库定义的大多数流输出和输入运算符确实被定义为流类的成员,但当您为自己的类型实现输出和输入操作时,您无法更改标准库的数据流类型
这就是为什么您需要为自己的类型实现这些(<<
和>>
(运算符作为非成员函数的原因。由于您需要在运算符定义中访问类对象的私有/受保护成员变量,因此需要将这些重载运算符声明为类的友元。
为什么运算符<lt;重载函数是否需要返回对ostream对象的引用,该对象也是它的输入参数?
通过返回对标准流对象的引用,可以使用对象链接。
你可以打这样的电话:
out<<obj1<<obj2;
模板用于具有重载函数的用户定义类?
模板可以帮助您实现通用函数和类,这些函数和类可以针对不同的数据类型,编译器负责为这些特定的数据类型生成代码。因此,以上两点并不相关。
强烈建议阅读以下常见问题条目:
操作员过载
[1]它需要成为友元,因为它试图访问私有成员变量m_nCents
,该变量只能由Cents
的成员函数或Cents
的友元访问。
[2] 这是重载"流媒体运营商"的标准函数签名。这使得连接<<
s:成为可能
out << a << b;
相当于
(out << a) << b;
编辑:您似乎希望operator<<
成为该类的成员。这是不可能的,因为它的第一个操作数是ostream
,而不是Cents
。friend
实际上将其声明为非成员朋友函数。如果去掉friend
关键字,则将其声明为成员函数(因为它在类定义中(,但在这种情况下,它有太多的参数(签名中的两个,以及作为第一个参数的隐式Cents
,调用它的一个,如果您喜欢的话,还有this
指针(。
将operator<<
声明为流式传输的非成员函数是标准的方法,无论是否为friend
(取决于您是否需要friend
,或者以某种方式公开m_nCents
(。
它必须返回一个ostream并将其中一个作为参数,这样才能将多个调用链接在一起。
例如:
Cents a,b,c;
cout << a << b << c;
它必须是一个朋友,因为它不是一个成员函数,不管你在class
代码块中定义了什么。
让我进一步阐述一下这个概念。上述示例等效于以下内容:
op(op(op(cout,a),b),c);
其中"op"是重载运算符的实际函数名的简写。请注意,它不是在Cents的实例上调用的,事实上也不会有this
ptr,因为它就像一个独立的函数一样存在于类之外。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 呼叫运营商<<临时
- 基于boost的程序的静态链接——zlib问题