# friend operator with polymorphic behavior

This topic is 3817 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Well,I've derived aclass from an abstract one and I want to define a friend function( operator<< ) that would be polymorphic. Here are the specs of the classes:
#ifndef SHAPE_HPP
#define SHAPE_HPP

#include <iostream>
#include <fstream>

using std::ostream;
using std::ofstream;

class Shape
{
public:

Shape();
~Shape();

virtual void draw()const=0;
};

Shape::Shape()
{
}

Shape::~Shape()
{
}

#endif


And the derived class:
#ifndef RECTANGLE_HPP
#define RECTANGLE_HPP

#include <iostream>
#include <fstream>
#include <vector>
#include <GL/GL.h>
#include <GL/glu.h>
#include "Vector3D.hpp"
#include "Shape.hpp"

using std::vector;
using std::ostream;
using std::ofstream;
using std::cout;
using std::endl;

template<class T>
class Rectangle : public Shape
{
public:

Rectangle();
Rectangle( const T& , const T& );
~Rectangle();

void draw()const;

template<class U> friend ostream& operator<<( ostream& , const Rectangle<U>& );
template<class U> friend ofstream& operator<<( ofstream& , const Rectangle<U>& );

protected:

T a;
T b;
vector<Vector3<T> > vertices;
};

template<class T>
Rectangle<T>::Rectangle()
{
}

template<class T>
Rectangle<T>::Rectangle( const T& _a , const T& _b )
{
a = _a;
b = _b;

vertices.reserve( 4 );
vertices.push_back( Vector3<T>( -a/2 , -b/2 , 0 ) );
vertices.push_back( Vector3<T>( a/2 , -b/2 , 0 ) );
vertices.push_back( Vector3<T>( a/2 , b/2 , 0 ) );
vertices.push_back( Vector3<T>( -a/2 , b/2 , 0 ) );
}

template<class T>
Rectangle<T>::~Rectangle()
{
}

template<class T>
void Rectangle<T>::draw()const
{
}

template<class T>
ostream& operator<<( ostream& out , const Rectangle<T>& s )
{
for( int i = 0 ; i < 4 ; ++i )
{
out << i << ":(" << s.vertices[0] << "," << s.vertices[1] << "," << s.vertices[2] << ")" << endl;
}

return out;
}

template<class T>
ofstream& operator<<( ofstream& out , const Rectangle<T>& s )
{
for( int i = 0 ; i < 4 ; ++i )
{
out << i << ":(" << s.vertices[0] << "," << s.vertices[1] << "," << s.vertices[2] << ")" << endl;
}

return out;
}

template<>
void Rectangle<float>::draw()const
{
glVertex3f( vertices[0][0] , vertices[0][1] , vertices[0][2] );
glVertex3f( vertices[1][0] , vertices[1][1] , vertices[1][2] );
glVertex3f( vertices[2][0] , vertices[2][1] , vertices[2][2] );
glVertex3f( vertices[3][0] , vertices[3][1] , vertices[3][2] );
glEnd();
}

template<>
void Rectangle<double>::draw()const
{
glVertex3d( vertices[0][0] , vertices[0][1] , vertices[0][2] );
glVertex3d( vertices[1][0] , vertices[1][1] , vertices[1][2] );
glVertex3d( vertices[2][0] , vertices[2][1] , vertices[2][2] );
glVertex3d( vertices[3][0] , vertices[3][1] , vertices[3][2] );
glEnd();
}

#endif


I want actually this: Shape* s = new Rectangle<double>( 50.0 , 20.0 ); cout << s << endl; How can I achieve this? [Edited by - johnstanp on May 6, 2008 6:29:14 AM]

##### Share on other sites
You could define a (pure) virtual function in your base class that does the outputting into the stream and then define global operator<<(std::ostream&, Base const&) that would call this function — it doesn’t even have to be friend this way. E.g.:
#include <iostream>class Base {public:  virtual ~Base() { }  virtual void print(std::ostream&) const = 0;};template <typename T>class Derived  : public Base{public:  Derived(T a, T b);  virtual void print(std::ostream& stream) const;private:  T a;  T b;};template <typename T>Derived<T>::Derived(T a, T b)  : a(a)  , b(b){ }template <typename T>void Derived<T>::print(std::ostream& stream) const {  stream << '[' << a << "; " << b << ']';}std::ostream& operator<<(std::ostream& stream, Base const& b) {  b.print(stream);  return stream;}int main() {  Base* b = new Derived<double>(3.14, 2.71);  std::cout << *b << '\n';  delete b;}

##### Share on other sites
Quote:
 Original post by OxydYou could define a (pure) virtual function in your base class that does the outputting into the stream and then define global operator<<(std::ostream&, Base const&) that would call this function — it doesn’t even have to be friend this way. E.g.:*** Source Snippet Removed ***

I like your solution:simple,clean and elegant.
I'll code it.

Thanks for being that quick to answer.

PS:what are the tags to use for "code quoting"?

##### Share on other sites
Quote:
 Original post by johnstanpPS:what are the tags to use for "code quoting"?

You can put larger code snippets in [source] [/source] tags and smaller ones in [code] [/code] tags — the latter only gives you monospaced font, without hilighting or scrollable frame. x)

##### Share on other sites
Quote:
 Original post by johnstanpPS:what are the tags to use for "code quoting"?

Read the FAQ for nice formatting tips

##### Share on other sites
Quote:
Original post by rolkA
Quote:
 Original post by johnstanpPS:what are the tags to use for "code quoting"?

Read the FAQ for nice formatting tips

Thanks...I'm so lazy. lol

1. 1
Rutin
26
2. 2
3. 3
4. 4
5. 5

• 10
• 13
• 19
• 14
• 9
• ### Forum Statistics

• Total Topics
632942
• Total Posts
3009339
• ### Who's Online (See full list)

There are no registered users currently online

×