C++ 运算符 << 必须只接受一个参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10744787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
operator << must take exactly one argument
提问by As As
a.h
啊
#include "logic.h"
...
class A
{
friend ostream& operator<<(ostream&, A&);
...
};
logic.cpp
逻辑.cpp
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...
When i compile, it says:
当我编译时,它说:
std::ostream& logic::operator<<(std::ostream&, A&)' must take exactly one argument.
std::ostream& logic::operator<<(std::ostream&, A&)' 必须只取一个参数。
What is the problem?
问题是什么?
回答by Cat Plus Plus
The problem is that you define it inside the class, which
问题是你在类中定义它,它
a) means the second argument is implicit (this
) and
a) 表示第二个参数是隐式的 ( this
) 和
b) it will not do what you want it do, namely extend std::ostream
.
b)它不会做你想做的事,即扩展std::ostream
。
You have to define it as a free function:
您必须将其定义为自由函数:
class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);
回答by Jonathan Wakely
A friend function is not a member function, so the problem is that you declare operator<<
as a friend of A
:
友元函数不是成员函数,所以问题是你声明operator<<
为的友元A
:
friend ostream& operator<<(ostream&, A&);
then try to define it as a member function of the class logic
然后尝试将其定义为类的成员函数 logic
ostream& logic::operator<<(ostream& os, A& a)
^^^^^^^
Are you confused about whether logic
is a class or a namespace?
您是否对logic
是类还是命名空间感到困惑?
The error is because you've tried to define a member operator<<
taking two arguments, which means it takes three arguments including the implicit this
parameter. The operator can only take two arguments, so that when you write a << b
the two arguments are a
and b
.
错误是因为您试图定义一个带有operator<<
两个参数的成员,这意味着它需要三个参数,包括隐式this
参数。运算符只能带两个参数,所以当你写a << b
这两个参数时是a
and b
。
You want to define ostream& operator<<(ostream&, const A&)
as a non-member function, definitely not as a member of logic
since it has nothing to do with that class!
要定义ostream& operator<<(ostream&, const A&)
为一个非-member功能,绝对不是其中的一名成员logic
,因为它无关,与一流!
std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << a.number;
}
回答by Dan Truong
I ran into this problem with templated classes. Here's a more general solution I had to use:
我在模板化类中遇到了这个问题。这是我必须使用的更通用的解决方案:
template class <T>
class myClass
{
int myField;
// Helper function accessing my fields
void toString(std::ostream&) const;
// Friend means operator<< can use private variables
// It needs to be declared as a template, but T is taken
template <class U>
friend std::ostream& operator<<(std::ostream&, const myClass<U> &);
}
// Operator is a non-member and global, so it's not myClass<U>::operator<<()
// Because of how C++ implements templates the function must be
// fully declared in the header for the linker to resolve it :(
template <class U>
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj)
{
obj.toString(os);
return os;
}
Now: * My toString() function can't be inline if it is going to be tucked away in cpp. * You're stuck with some code in the header, I couldn't get rid of it. * The operator will call the toString() method, it's not inlined.
现在: * 如果我的 toString() 函数要隐藏在 cpp 中,则它不能内联。* 你被标题中的一些代码困住了,我无法摆脱它。* 操作符将调用 toString() 方法,它不是内联的。
The body of operator<< can be declared in the friend clause or outside the class. Both options are ugly. :(
operator<< 的主体可以在友元子句中或在类外声明。这两种选择都很丑陋。:(
Maybe I'm misunderstanding or missing something, but just forward-declaring the operator template doesn't link in gcc.
也许我误解或遗漏了一些东西,但只是向前声明操作员模板在 gcc 中没有链接。
This works too:
这也有效:
template class <T>
class myClass
{
int myField;
// Helper function accessing my fields
void toString(std::ostream&) const;
// For some reason this requires using T, and not U as above
friend std::ostream& operator<<(std::ostream&, const myClass<T> &)
{
obj.toString(os);
return os;
}
}
I think you can also avoid the templating issues forcing declarations in headers, if you use a parent class that is not templated to implement operator<<, and use a virtual toString() method.
我认为您还可以避免在标题中强制声明的模板问题,如果您使用未模板化的父类来实现 operator<<,并使用虚拟 toString() 方法。
回答by Rinzler
If you define operator<<
as a member function it will have a different decomposed syntax than if you used a non-member operator<<
. A non-member operator<<
is a binary operator, where a member operator<<
is a unary operator.
如果您定义operator<<
为成员函数,它将具有与使用 non-member 不同的分解语法operator<<
。非成员operator<<
是二元运算符,其中成员operator<<
是一元运算符。
// Declarations
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
// This is a member unary-operator, hence one argument
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
// This is a non-member binary-operator, 2 arguments
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
So.... how do you really call them? Operators are odd in some ways, I'll challenge you to write the operator<<(...)
syntax in your head to make things make sense.
所以……你怎么称呼他们?运算符在某些方面很奇怪,我将挑战您operator<<(...)
在头脑中编写语法以使事情有意义。
MyObj mo;
// Calling the unary operator
mo << std::cout;
// which decomposes to...
mo.operator<<(std::cout);
Or you could attempt to call the non-member binary operator:
或者您可以尝试调用非成员二元运算符:
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
You have no obligation to make these operators behave intuitively when you make them into member functions, you could define operator<<(int)
to left shift some member variable if you wanted to, understand that people may be a bit caught off guard, no matter how many comments you may write.
当你把它们变成成员函数时,你没有义务让这些操作符的行为直观,如果你愿意,你可以定义operator<<(int)
左移一些成员变量,明白人们可能有点措手不及,不管你有多少评论写。
Almost lastly, there may be times where both decompositions for an operator call are valid, you may get into trouble here and we'll defer that conversation.
几乎最后,有时操作员调用的两种分解都是有效的,您可能会在这里遇到麻烦,我们将推迟该对话。
Lastly, note how odd it might be to write a unary member operator that is supposed to look like a binary operator (as you can make member operators virtual..... also attempting to not devolve and run down this path....)
最后,请注意编写一个看起来像二元运算符的一元成员运算符可能是多么奇怪(因为您可以使成员运算符成为虚拟运算符..... 还试图不下放并沿着这条路径运行.... )
struct MyObj
{
// Note that we now return the ostream
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
This syntax will irritate many coders now....
这种语法现在会激怒许多编码人员......
MyObj mo;
mo << std::cout << "Words words words";
// this decomposes to...
mo.operator<<(std::cout) << "Words words words";
// ... or even further ...
operator<<(mo.operator<<(std::cout), "Words words words");
Note how the cout
is the second argument in the chain here.... odd right?
请注意cout
这里的链中的第二个参数是如何....奇怪吧?