0
votes

I have read some similar questions and answers at SO, but don't really understand the answers there. My apologies, if this is a duplicate.

Have a base class like this.

class CParam
{
    public:
        virtual void PrintData(ostream &OutStream) = 0;
};

Now I inherit from this:

class CUInt32:public CParam
{
    public:
          void PrintData(ostream &OutStream);
}

void CUInt32::PrintData(ostream &OutStream)
{
    // Write some data to OutStream Here
}

I overload operator << for CUInt32 class

inline ostream   &operator<<(ostream &OutStream, CUInt32 &UInt32Obj)
{
    UInt32Obj.PrintData(OutStream);
    return (OutStream);
}

In int main() function I do the following:

int main()
{
    CParam *cp = new CUInt32(ANALOG);

    cout << *cp;// Error
    return 0;
}

I get an error saying error: no match for 'operator<<' in 'std::cout << *cp'|

My questions are

  1. Is it possible to use polymorphic base class pointers with cout?
  2. If yes, how we could do this?

Thanks for your time!

3
Instead of overloading operator << for CUInt32, overload it for CParam. - Casey
Not quite sure how I could do this since the second argument of inline ostream &operator<<(ostream &OutStream, CUInt32 &UInt32Obj) is different for each derived class. - NeonGlow
Also (even though it's not causing problems here) it's good to make it const reference: inline ostream &operator<<(ostream &OutStream, const CParam& obj) - Artem Tokmakov
stackoverflow.com/questions/17610986 may help you - it's basically the identical problem - nijansen
Suggestion: Change void PrintData(ostream &OutStream) to std::string PrintData () const and simply use it with std::cout, printf(), fprint(), anywhere you want. - iammilind

3 Answers

3
votes

The operator is not defined for the base class. Simply change this:

inline ostream   &operator<<(ostream &OutStream, CUInt32 &UInt32Obj)
{
    UInt32Obj.PrintData(OutStream);
    return (OutStream);
}

to this:

inline ostream   &operator<<(ostream &OutStream, CParam& cParam)
{
    cParam.PrintData(OutStream);
    return (OutStream);
}

Basically, defining the PrintData in the base class as virtual/abstract ensures it will be available for all subclasses and the correct function will be called.

3
votes

Along with the obvious point (operator<< should take a reference to a const base) you also want to change your definition of PrintData to make it a constmember function, so it can be invoked on a const object. The resulting code ends up something like this:

struct CParam {
    virtual void PrintData(ostream &OutStream) const = 0;
};

struct CUInt32 : CParam {
    void PrintData(ostream &OutStream) const {}
};

ostream &operator<<(ostream &OutStream, CParam const &UInt32Obj) {
    UInt32Obj.PrintData(OutStream);
    return (OutStream);
}
0
votes

Since overloading code uses PrintData, you could define the function at base class level itself. Since compiler couldn't find any overloading at base class level, it throws exception.