简体   繁体   English

如何在没有友元函数的情况下重载<<运算符

[英]How to overload << operator without friend function

I am trying to overload << operator to print Currency (user defined type)我正在尝试重载 << 运算符来打印货币(用户定义的类型)

#include <iostream>
using namespace std;

struct Currency
{
  int Dollar;
  int Cents;

  ostream& operator<< (ostream &out)
  {
    out << "(" << Dollar << ", " << Cents << ")";
    return out;
  }
};



template<typename T>
void DisplayValue(T tValue)  
{
   cout << tValue << endl;
}

int main() {

Currency c;
c.Dollar = 10;
c.Cents = 54;

DisplayValue(20); // <int>
DisplayValue("This is text"); // <const char*>
DisplayValue(20.4 * 3.14); // <double>
DisplayValue(c); // Works. compiler will be happy now. 
return 0;
}

But getting the following error.但得到以下错误。

prog.cpp: In instantiation of ‘void DisplayValue(T) [with T = Currency]’:
prog.cpp:34:16:   required from here
prog.cpp:22:9: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
    cout << tValue << endl;
         ^
In file included from /usr/include/c++/4.8/iostream:39:0,
                 from prog.cpp:1:
/usr/include/c++/4.8/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Currency]’
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^

Can anyone help me if i am missing any thing or doing anything wrong here?如果我在这里遗漏了任何东西或做错了什么,任何人都可以帮助我吗?

You don't put it into your class, you put if afterwards.你不把它放在你的类中,你放在之后。 Since your members are public there is no need to declare it a friend :由于您的成员是public因此无需将其声明为friend

struct Currency
{
    int Dollar;
    int Cents;
};

ostream& operator<< (ostream &out, const Currency& c)
{
    out << "(" << c.Dollar << ", " << c.Cents << ")";
    return out;
}

First you need to fix the operator by adding Currency const& c as the second parameter (as it come s on the right hand side).首先,您需要通过添加Currency const& c作为第二个参数来修复运算符(因为它位于右侧)。

Then you have two options:那么你有两个选择:

1: Add Friend 1:添加好友

struct Currency
{
  int Dollar;
  int Cents;

  friend ostream& operator<< (ostream &out, Currency const& c)
  {
    return out << "(" << c.Dollar << ", " << c.Cents << ")";
  }
};

2: Move the definition outside the class 2:将定义移到类外

struct Currency
{
  int Dollar;
  int Cents;
};

ostream& operator<< (ostream &out, Currency const& c)
{
  return out << "(" << C.Dollar << ", " << c.Cents << ")";
}

Either works and is fine.要么工作,要么没问题。
Personally I like option-1 as it documents the tight coupling of the output operator to the class that it is outputting.我个人喜欢 option-1,因为它记录了输出运算符与其输出的类的紧密耦合。 But this is such a simple case that either works just fine.但这是一个如此简单的案例,两者都可以正常工作。

The reason that it can not be a member is that the first parameter is a stream (the left hand side value of the operator is the first parameter).它不能是成员的原因是第一个参数是一个流(运算符的左侧值是第一个参数)。 This does not work for members as the first parameter is the hidden this parameter.这对成员不起作用,因为第一个参数是隐藏的 this 参数。 So technically you could add this method to std::ostream .因此,从技术上讲,您可以将此方法添加到std::ostream Unfortunately you don't have accesses (and not allowed to) modify std::ostream .不幸的是,您无权(也不允许)修改std::ostream As a result you must make it a free standing function.因此,您必须使其成为独立的功能。

Example showing it can be a member:显示它可以是成员的示例:

struct X
{
    std::ostream operator<<(int y)
    {
        return std::cout << y << " -- An int\n";
    }
};
int main()
{
    X   x;
    x << 5;
}

That works fine here.这在这里工作正常。 This is because the compiler translates这是因为编译器翻译

x << 5;

into进入

// not real code (pseudo thought experiment code).
operator<<(x, 5)
      // Equivalent to:
                X::operator<<(int y)
      // or
                operator<<(X& x, int y) 

Because x has a member function operator<< this works fine.因为 x 有一个成员函数operator<<这工作正常。 If x did not have a member function called operator<< then the compiler would look for a free standing function that takes two parameters with X as the first and int as the second.如果x没有名为operator<<的成员函数,那么编译器将寻找一个独立的函数,该函数接受两个参数,其中X作为第一个参数, int作为第二个参数。

Overload it like below, and put it outside of class declaration (you don't need friendship!):像下面这样重载它,并将它放在类声明之外(你不需要友谊!):

ostream& operator<< (ostream &out, const Currency &c)
{                                 //^^^^^^^^^^^^^^^^
  out << "(" << c.Dollar << ", " << c.Cents << ")";
  return out;
}

Funny thing with your code is, you have to use the operator like this:您的代码有趣的是,您必须像这样使用运算符:

c << cout; // !!

The way you've written your inserter method, the only way to get it to work would be to do:您编写插入器方法的方式,让它工作的唯一方法是:

c << std::cout;

But instead, if you know your inserters won't need to access any private variables, simply do as the other answers say and create a global function that takes both arguments:但是,相反,如果您知道您的插入器不需要访问任何私有变量,只需按照其他答案的说明进行操作并创建一个接受两个参数的全局函数:

std::ostream& operator <<(std::ostream& os, const Currency& c);
#include<iostream>
using namespace std;
class myclass
{
    int x;
    public:
    myclass() //constructor
    {
        x=5;
    }

    friend ostream& operator<<(ostream &outStreamObject,myclass &object); //standard way

    void operator<<(ostream &outStreamObject) //Another way.
    {
        outStreamObject<<this->x;
    }


};
 ostream& operator<<(ostream &outStreamObject,myclass &object)
{
    cout<<object.x;
    return outStreamObject;
}
int main()
{
    //standard way of overload the extraction operator
    myclass object1,object2;
    cout<<object1<<" "<<object2;
    cout<<endl;
    //overloading the extraction operator with using friend function
    object1.operator<<(cout);
    return 0;
}

It is not at all necessary that the insertion and the extraction operators can be overloaded only by using the friend function.完全没有必要仅使用友元函数就可以重载插入和提取运算符。 The above code overloads the extraction operator with and without the friend function.上面的代码使用和不使用友元函数重载了提取运算符。 The friend function implementation is favoured because cout can be used the way it is used for other datatypes.友元函数实现是受欢迎的,因为 cout 可以像用于其他数据类型一样使用。 Similary you can overload the insertion operator.类似地,您可以重载插入运算符。

You need to make it friend : Also you need to give it the right arguments.你需要让它成为朋友:你还需要给它正确的论据。 an ostream and the currency. ostream 和货币。

  friend ostream& operator<< (ostream& stream, const Currency& c )
  {
    stream << "(" << c.Dollar << ", " << c.Cents << ")";
    return stream;
  }

Edit:编辑:
As you can see in the comments, you don't have to make it friend.正如你在评论中看到的,你不必把它变成朋友。 You can put it outside the structure.你可以把它放在结构之外。

Currency c;
c.Dollar = 10;
c.Cents = 54;

DisplayValue(c); // Works. compiler will be happy now. 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM