Search code examples
c++inheritanceheader-filesostreamistream

ostream in class does not have a type


Just got into C++ and I have a quick question.

After compiling with

g++ *.cpp -o output

I receive this error:

error: 'ostream' in 'class Dollar' does not name a type

These are my three files:

main.cpp

#include <iostream>
#include "Currency.h"
#include "Dollar.h"

using namespace std;

int main(void) {
    Currency *cp = new Dollar;

    // I want this to print "printed in Dollar in overloaded << operator"
    cout << cp;
    return 0;
}

Dollar.cpp

#include <iostream>
#include "Dollar.h"

using namespace std;

void Dollar::show() {
    cout << "printed in Dollar";
}

ostream & operator << (ostream &out, const Dollar &d) {
    out << "printed in Dollar in overloaded << operator";
}

Dollar.h

#include "Currency.h"

#ifndef DOLLAR_H
#define DOLLAR_H

class Dollar: public Currency {
    public:
        void show();
};

ostream & operator << (ostream &out, const Dollar &d);

#endif

Thank you for your time, and everything helps!


Solution

  • You have a number of errors in the code.

    1. You heavily use using namespace std. This is a bad practice. In particular, this led to the error you faced: you don't have using namespace std in Dollar.h, thus the compiler has no idea what ostream means. Either put using namespace std in Dollar.h too, or better just stop using it and specify the std namespace directly, as in std::ostream.
    2. You use std::ostream in your headers, but you don't include the corresponding standard library header <ostream> in them (<ostream> contains the definition of std::ostream class; for the full I/O library include <iostream>). A really good practice is to include all the dependencies of the header in the header itself, so that it is self-contained and can be safely included anywhere.
    3. You are implementing a stream output operator with signature std::ostream & operator << (std::ostream &, Dollar const &), which is perfectly valid. However, you call it for a pointer to type Dollar. You should rather call it with the object itself, not the pointer, so you should dereference the pointer: std::cout << *cp;.
    4. You implemented the output operator for the Dollar class, but use it for a variable of type Currency: this won't work. There is a way to do this - there do exist virtual methods for this exact reason. However, in this case the operator is a free function, thus it cannot be virtual. So, you should probably add a virtual print method to your Currency class, implement it in Dollar, and call it from output operator:

      #include <iostream>
      
      class Currency {
      public:
          virtual void print (std::ostream &) const = 0;
      };
      
      class Dollar : public Currency {
          void print (std::ostream & out) const override {
              out << "A dollar";
          }
      };
      
      std::ostream & operator << (std::ostream & out, Currency const & c) {
          c.print(out);
          return out;
      }
      
      int main(/* void is redundant here */) {
          Currency *cp = new Dollar;
          std::cout << *cp;
          // return 0 is redundant in main
      }