首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >运算符<<必须只接受一个参数

运算符<<必须只接受一个参数
EN

Stack Overflow用户
提问于 2012-05-25 04:26:47
回答 6查看 116.6K关注 0票数 98

a.h

代码语言:javascript
复制
#include "logic.h"
...

class A
{
friend ostream& operator<<(ostream&, A&);
...
};

logic.cpp

代码语言:javascript
复制
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...

当我编译时,它说:

std::ostream& logic::operator<<(std::ostream&,A&)‘必须只有一个参数。

有什么问题吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-05-25 04:28:54

问题是您在类中定义它,这

a)表示第二个参数是隐式的(this),并且

b)它不会做你想做的事情,也就是扩展std::ostream

你必须将它定义为一个自由函数:

代码语言:javascript
复制
class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);
票数 141
EN

Stack Overflow用户

发布于 2012-05-25 05:13:53

友元函数不是成员函数,所以问题是您将operator<<声明为A的友元

代码语言:javascript
复制
 friend ostream& operator<<(ostream&, A&);

然后尝试将其定义为类logic的成员函数

代码语言:javascript
复制
 ostream& logic::operator<<(ostream& os, A& a)
          ^^^^^^^

您是否对logic是类还是名称空间感到困惑?

错误是因为您试图定义一个带有两个参数的成员operator<<,这意味着它需要包括隐式this参数在内的三个参数。运算符只能接受两个参数,因此当您编写a << b时,两个参数是ab

您希望将ostream& operator<<(ostream&, const A&)定义为-member函数,而不是logic的成员,因为它与该类无关!

代码语言:javascript
复制
std::ostream& operator<<(std::ostream& os, const A& a)
{
  return os << a.number;
}
票数 52
EN

Stack Overflow用户

发布于 2017-06-23 10:27:18

我在使用模板化类时遇到了这个问题。下面是我不得不使用的一个更通用的解决方案:

代码语言:javascript
复制
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;
}

现在:*如果我的toString()函数要隐藏在cpp中,它就不能是内联的。*你被头中的一些代码卡住了,我无法摆脱它。*操作符将调用toString()方法,它不是内联的。

operator<<的主体可以在friend子句中声明,也可以在类外部声明。这两种选择都很丑陋。:(

也许我误解或遗漏了什么,但只是向前声明运算符模板并不会链接到gcc。

这也行得通:

代码语言:javascript
复制
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;
    }
}

我认为,如果使用未模板化的父类实现operator<<,并使用虚拟toString()方法,还可以避免强制在头部中声明的模板化问题。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10744787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档