简体   繁体   中英

Use of std::ostream for Printing Vectors

I'm quite new to C++ and I am trying to print out a vector of Institutions, which is a type of object that I created. The creation of the object and the rest of my program runs just fine but when I try to print out the vector, the "<<" gives an error that says "operand types are std::ostream".

void PrintVector(const vector<Institution> &institutions)
{
    for (int x = 0; x < institutions.size; x++)
    {
        cout << institutions.at(x) << endl;
    }
}

I've tried to do research on what std::ostream is or what it does but since I don't know a lot about C++ (or programming in general), I can't understand any of the sites that explain it. Why won't the usual "cout <<" work in this situation? Can anybody explain to me what this means or if there is a different way to print out my vector that doesn't require this?

Any help is appreciated, thanks.

You may want to overload the ostream operator (<<) for your class Institution: https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx

ostream& operator<<(ostream& os, const Institution& inst)
{
    os << inst.foo; /* some member variable */;
    return os;
}

The problem is that a C++ ostream (which cout is) does not have any way to print out an Institution object. You are going to have to overload the operator<< function in our Institution as described in the link posted in the other answer ( https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx?f=255&MSPPError=-2147217396 ) in order to get it to work.

You have to provide an operator << for your class:

std::ostream& operator << (std::ostream& os, const Institution& institution)
{
    os << institution.getValue();
    // ...
    return os;
}

operator<< is overloaded to allow outputting built-in types like int and double . But you'll need to tell the compiler how to output your class Institution by overloading it again:

std::ostream& operator<<(std::ostream& os, const Institution& inst) {
    os << inst.name(); // or something
    return os;
}

There are at least two problems with the code that you have shown.

1)

for (int x = 0; x < institutions.size; x++)

std::vector::size() is a class method, a function. It is not a class member. This should read:

for (int x = 0; x < institutions.size(); x++)

2)

cout << institutions.at(x) << endl;

Unfortunately, std::ostream knows nothing about your Institution class. You will need to implement a class method, such as display() , that will assemble a printable representation of the contents of the class, and write it to the output stream. So, for example, if the class contains two std::string s, called name , and address :

class Institution {

// ...

public:

      void display(std::ostream &o)
      {
           o << name << std::endl << address << std::endl;
      }
// ...
};

... or, in whatever formatting style you want your class instances to be displayed. Then:

for (int x = 0; x < institutions.size(); x++)
     institutions.at(x).display(std::cout);

3)

Well, here's a bonus problem with your code. It is actually written in an obsolete C++ dialect that went out of style decades ago. Whatever textbook you're using to learn C++, you need to ditch it, and pick up a textbook that was written this century, and which will teach you modern C++. In modern C++, this becomes a much more readable:

for (const auto &institution:institutions)
     institution.display(std::cout);

The answers here are all correct. I will provide a slightly different answer to the displaying issue, as this is a recurring problem. What you can do is define an abstract class, we'll call it IDisplay , which declares a pure virtual function std::ostream& display(std::ostream&) const and declares operator<< as a friend. Then every class that you want to be display-able must inherit from IDisplay and consequently implement the display member function. This approach reuses the code and is pretty elegant. Example below:

#include <iostream>

class IDisplay
{
private:
    /**
    * \brief Must be overridden by all derived classes
    *
    * The actual stream extraction processing is performed by the overriden
    * member function in the derived class. This function is automatically
    * invoked by friend inline std::ostream& operator<<(std::ostream& os,
    * const IDisplay& rhs).
    */
    virtual std::ostream& display(std::ostream& os) const = 0;

public:
    /**
    * \brief Default virtual destructor
    */
    virtual ~IDisplay() = default;

    /**
    * \brief Overloads the extraction operator
    *
    * Delegates the work to the virtual function IDisplay::display()
    */
    friend inline
    std::ostream& operator<<(std::ostream& os, const IDisplay& rhs)
    {
        return rhs.display(os);
    }
}; /* class IDisplay */

class Foo: public IDisplay
{
public:
    std::ostream& display(std::ostream& os) const override 
    {
        return os << "Foo";
    }
};

class Bar: public IDisplay
{
public:
    std::ostream& display(std::ostream& os) const override 
    {
        return os << "Bar";
    }
};

int main() 
{
    Foo foo;
    Bar bar;
    std::cout << foo << " " << bar;    
}

Live on Coliru

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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