Hi all,

I've got quite a simple question and after searching here and on other websites I can't seem to resolve what the "correct way" of doing this is in C++. Below is a simple piece of code illustrating what I am trying to do:

#include <iostream>

class BaseClass
{
public:

    BaseClass( ){ }

    ~BaseClass( ){ }

    friend std::ostream& operator<<( std::ostream& stream, BaseClass* pointerToBaseClass )
    {
        std::cout << "Value in this object is set to: " 
                  << pointerToBaseClass->value << std::endl;
    }

protected:

    double value;

private:
};

class DerivedClass : public BaseClass
{
public:

    DerivedClass( ){ }

    ~DerivedClass( ){ }

protected:
private:
}

int main( )
{
    DerivedClass myDerivedClass;

    myDerivedClass.value = 10.0;

    std::cout << myDerivedClass << std::endl;

    return 0;
}

This for some reason is not working for me. All the examples I've seen define the second argument of the ostream operator overload as: BaseClass& baseClass. If I do this however, I can't seem to use inheritance for the operator overload for the DerivedClass class. I'm not quite sure why the way I'm doing it doesn't work, as the pointer given is in affect simply a memory address too.

The error I'm getting from the compiler is:

Undefined symbols:
"operator<<(std::basic_ostream<char, std::char_traits<char> >&, BaseClass const&)", referenced from:
_main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

I'm guessing this is just something simple that boils down to understand how the operator overloading actually works. I've got my head in bit of a knot now after hunting down solutions online, so I'd appreciate it if someone could let me know what's going wrong with what I've done.

Thanks in advance!

Cheers,

Spidey

Recommended Answers

All 4 Replies

The problem is that friend methods don't get passed down to inherited classes. Here is an illustration of what I mean:
Won't work, friend method does not get passed down:

#include <iostream>
using namespace std;
class Base
{
    public:
    friend void out(){cout<<"BASE";}
};
class Derived:public Base
{};
int main()
{
    Derived bob;
    bob.out();
    return 0;
}

Will work, out is inherited from Base:

#include <iostream>
using namespace std;
class Base
{
    public:
    void out(){cout<<"BASE";}
};
class Derived:public Base
{};
int main()
{
    Derived bob;
    bob.out();
    return 0;
}

Hope this helps. (In short I think you will have to either write another << operator or maybe find out the syntax for a virtual << operator overload)

This is how I would solve this problem

#include <iostream>

class BaseClass
{
public:

    BaseClass( ){ }

    ~BaseClass( ){ }

	double getitsvalue() const { return value; }
	void setitsvalue(double val) { value = val; }

protected:

    double value;

};

class DerivedClass : public BaseClass
{
public:

    DerivedClass( ) { }

    ~DerivedClass( ){ }

};

std::ostream& operator <<(std::ostream & out, const BaseClass & b)
{
	return out << b.getitsvalue();
} 

int main( )
{
    DerivedClass myDerivedClass;

    myDerivedClass.setitsvalue(10.0);

    std::cout << myDerivedClass << std::endl;

    return 0;
}

Since DerivedClass objects can be sliced down to BaseClass this'll work.

In addition to gerard143's solution, which is fine. You may want to make getitsvalue virtual.

This is problem is a specialization of the common construction:

class Base
{
   public:
    // Stuff... 
    virtual void write(std::ostream&) const;   
};

class Derived : public Base 
{
   public:
   virtual void write(std::ostream&) const;
};

std::ostream& operator<<(std::ostream& Out,const Base& A) 
{
   return Out<<A;
}

I only really bring that up since it is so common, that you will see that construct in many different books and open-source programs. [Note the operator<< is sometime templated with all the different classes in the program.]

Hi everyone,

Thanks for the feedback, I knew it was something as simple as friendship and inheritance not working together. Since the derived classes all have their own local attributes too, I've decided to just overload the ostream operator for all the derived classes individually. Bit of a pain to do, but that way all the info is included for each derived class now.

Thanks for the feedback.

Cheers,

Spidey

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.