Is this the right way to redirect output from a class to another?

J

Jason

Hello,

I have a class, transCore, that does certain work, and by default, prints
its progress to the stand output.

Later, I will to write a GUI class that encapsulate the transCore class. I
would like to redirect/intercept the output of transCore class to this GUI
class. I wrote a sample program that demonstrate how I did it, but I am not
sure if it's any good. Can anyone critic my code? If there's any
non-standard conforming code or a better way to redirect output, please let
me know. Thank you.

/* program start */

#include<iostream>
#include<string>
using namespace std;
class BaseDisplayFunctor
{
private:
public:
virtual void print(const string &)=0;
};

template<class T>
class MyDisplayFunctor:public BaseDisplayFunctor
{
private:
//object pointer
T *object_ptr;
//function pointer to display
void (T::*func_ptr)(const string &);
public:
MyDisplayFunctor(T* obj, void (T::*Display)(const string&))
{
object_ptr = obj;
func_ptr = Display;
}
virtual void print(const string &s)
{
(*object_ptr.*func_ptr)(s);
}
~MyDisplayFunctor(){}
};
/*
Class: TRANSCORE

PURPOSE: this class will does all works and print progress to
the screen
*/
class TransCore
{
private:
BaseDisplayFunctor *BDF;
void print(const string& s)
{
if(BDF != NULL)
BDF->print(s);
else
cout<< s;
}
public:
TransCore(BaseDisplayFunctor *display){BDF = display;}
void dosomething()
{
print("does some work#1");
print("does some work#2");
}
~TransCore(){};
};
/*
Class: TEST

PURPOSE: Demonstrate how I would like to redirect simple output
*/
class Test
{
private:
TransCore *transCore;
MyDisplayFunctor<Test> *myDF;
void redirected_output(const string &s)
{
/*
Supposed to intercept whatever ouput from TRANSCORE to
a GUI display
*/
cout<<"Redirected: " <<s<<endl;
}

public:
Test()
{
myDF = new MyDisplayFunctor<Test>(this, &Test::redirected_output);
transCore = new TransCore(myDF);
transCore->dosomething();
}
~Test(){delete transCore; delete myDF;}
};

int main(int argc, char **argv)
{
Test wow;
system("pause"); //prevent windowXP from closing my console
return 0;
}

/* program end */
 
M

Mike Wahler

Jason said:
Hello,

I have a class, transCore, that does certain work, and by default, prints
its progress to the stand output.

Later, I will to write a GUI class that encapsulate the transCore class. I
would like to redirect/intercept the output of transCore class to this GUI
class. I wrote a sample program that demonstrate how I did it, but I am not
sure if it's any good. Can anyone critic my code? If there's any
non-standard conforming code or a better way to redirect output, please let
me know. Thank you.

/* program start */

#include<iostream>
#include<string>
using namespace std;
class BaseDisplayFunctor
{
private:
public:
virtual void print(const string &)=0;
};

template<class T>
class MyDisplayFunctor:public BaseDisplayFunctor
{
private:
//object pointer
T *object_ptr;
//function pointer to display
void (T::*func_ptr)(const string &);
public:
MyDisplayFunctor(T* obj, void (T::*Display)(const string&))
{
object_ptr = obj;
func_ptr = Display;
}
virtual void print(const string &s)
{
(*object_ptr.*func_ptr)(s);
}
~MyDisplayFunctor(){}
};
/*
Class: TRANSCORE

PURPOSE: this class will does all works and print progress to
the screen
*/
class TransCore
{
private:
BaseDisplayFunctor *BDF;
void print(const string& s)
{
if(BDF != NULL)
BDF->print(s);
else
cout<< s;
}
public:
TransCore(BaseDisplayFunctor *display){BDF = display;}
void dosomething()
{
print("does some work#1");
print("does some work#2");
}
~TransCore(){};
};
/*
Class: TEST

PURPOSE: Demonstrate how I would like to redirect simple output
*/
class Test
{
private:
TransCore *transCore;
MyDisplayFunctor<Test> *myDF;
void redirected_output(const string &s)
{
/*
Supposed to intercept whatever ouput from TRANSCORE to
a GUI display
*/
cout<<"Redirected: " <<s<<endl;
}

public:
Test()
{
myDF = new MyDisplayFunctor<Test>(this, &Test::redirected_output);
transCore = new TransCore(myDF);
transCore->dosomething();
}
~Test(){delete transCore; delete myDF;}
};

int main(int argc, char **argv)
{
Test wow;
system("pause"); //prevent windowXP from closing my console
return 0;
}

/* program end */

#include <fstream>
#include <iostream>
#include <ostream>
#include <string>

void print(std::eek:stream& os, const std::string& s)
{
os << s;
}

int main()
{
std::ifstream ifs("filename");
std::string s1("Hello");
print(std::cout, s1); // to standard output
print(ifs, s1); // to file
return 0;
}

-Mike
 
D

David Rubin

Jason said:
Hello,

I have a class, transCore, that does certain work, and by default, prints
its progress to the stand output.

Later, I will to write a GUI class that encapsulate the transCore class. I
would like to redirect/intercept the output of transCore class to this GUI
class.

Two easy ways to do this are 1) have a 'setStream' function which
allows you to change the output stream from 'std::cout' (the default),
to some other 'std::eek:stream', or 2) set the output stream in a
constructor.
I wrote a sample program that demonstrate how I did it, but I am not
sure if it's any good. Can anyone critic my code?
Sure.

[snip]
#include<iostream>
#include<string>
using namespace std;
class BaseDisplayFunctor
{
private:
public:
virtual void print(const string &)=0;
};

This is not a functtor. AFAIK, "functor" is defined (largely) by the
presence of 'operator()'. In any case, inheritance is not the right
approach to solve your problem.
template<class T>
class MyDisplayFunctor:public BaseDisplayFunctor
{
private:
//object pointer
T *object_ptr;
//function pointer to display
void (T::*func_ptr)(const string &);
public:
MyDisplayFunctor(T* obj, void (T::*Display)(const string&))

This is just complicated. Pointers to functions are often helped by
typedefs.
{
object_ptr = obj;
func_ptr = Display;

Your naming scheme is wildly inconsistent. Typically, people name data
members with a leading or trailing underscore, or a mnemonic, such as
'd_'. So this would be written as

d_obj_p = obj; // d_obj_p is a data member of a pointer type
d_func = func; // d_func is a function pointer (note, no '_p')

These conventions obviate the need for coming up with funny argument
names, and make the code much more readable.
}
virtual void print(const string &s)
{
(*object_ptr.*func_ptr)(s);

You can take advantage of a language feature which allows you treat
pointers to functions as functions when making function calls:

object_ptr->func_ptr(s);
}
~MyDisplayFunctor(){}
};
/*
Class: TRANSCORE

PURPOSE: this class will does all works and print progress to
the screen
*/
class TransCore
{
private:
BaseDisplayFunctor *BDF;
void print(const string& s)
{
if(BDF != NULL)
BDF->print(s);
else
cout<< s;

You should flush the stream with 'std::flush' or 'std::endl'.
}
public:
TransCore(BaseDisplayFunctor *display){BDF = display;}
void dosomething()
{
print("does some work#1");
print("does some work#2");
}
~TransCore(){};
};
/*
Class: TEST

PURPOSE: Demonstrate how I would like to redirect simple output
*/

Why is this a class? Just put all these mechanics into 'main'.

HTH, /david
 
J

Jason

Thank you, David. I'll rethink my approach on output redirection.



David Rubin said:
"Jason" <[email protected]> wrote in message
Hello,

I have a class, transCore, that does certain work, and by default, prints
its progress to the stand output.

Later, I will to write a GUI class that encapsulate the transCore class. I
would like to redirect/intercept the output of transCore class to this GUI
class.

Two easy ways to do this are 1) have a 'setStream' function which
allows you to change the output stream from 'std::cout' (the default),
to some other 'std::eek:stream', or 2) set the output stream in a
constructor.
I wrote a sample program that demonstrate how I did it, but I am not
sure if it's any good. Can anyone critic my code?
Sure.

[snip]
#include<iostream>
#include<string>
using namespace std;
class BaseDisplayFunctor
{
private:
public:
virtual void print(const string &)=0;
};

This is not a functtor. AFAIK, "functor" is defined (largely) by the
presence of 'operator()'. In any case, inheritance is not the right
approach to solve your problem.
template<class T>
class MyDisplayFunctor:public BaseDisplayFunctor
{
private:
//object pointer
T *object_ptr;
//function pointer to display
void (T::*func_ptr)(const string &);
public:
MyDisplayFunctor(T* obj, void (T::*Display)(const string&))

This is just complicated. Pointers to functions are often helped by
typedefs.
{
object_ptr = obj;
func_ptr = Display;

Your naming scheme is wildly inconsistent. Typically, people name data
members with a leading or trailing underscore, or a mnemonic, such as
'd_'. So this would be written as

d_obj_p = obj; // d_obj_p is a data member of a pointer type
d_func = func; // d_func is a function pointer (note, no '_p')

These conventions obviate the need for coming up with funny argument
names, and make the code much more readable.
}
virtual void print(const string &s)
{
(*object_ptr.*func_ptr)(s);

You can take advantage of a language feature which allows you treat
pointers to functions as functions when making function calls:

object_ptr->func_ptr(s);
}
~MyDisplayFunctor(){}
};
/*
Class: TRANSCORE

PURPOSE: this class will does all works and print progress to
the screen
*/
class TransCore
{
private:
BaseDisplayFunctor *BDF;
void print(const string& s)
{
if(BDF != NULL)
BDF->print(s);
else
cout<< s;

You should flush the stream with 'std::flush' or 'std::endl'.
}
public:
TransCore(BaseDisplayFunctor *display){BDF = display;}
void dosomething()
{
print("does some work#1");
print("does some work#2");
}
~TransCore(){};
};
/*
Class: TEST

PURPOSE: Demonstrate how I would like to redirect simple output
*/

Why is this a class? Just put all these mechanics into 'main'.

HTH, /david
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top