Connecting Tech Pros Worldwide Forums | Help | Site Map

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

Jason
Guest
 
Posts: n/a
#1: Jul 22 '05
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 */



Mike Wahler
Guest
 
Posts: n/a
#2: Jul 22 '05

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



"Jason" <JC20032344@hotmail.com> wrote in message
news:eluWc.211$2F.144@trnddc05...[color=blue]
> 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[/color]
not[color=blue]
> 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[/color]
let[color=blue]
> 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 */[/color]

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

void print(std::ostream& 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


David Rubin
Guest
 
Posts: n/a
#3: Jul 22 '05

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


"Jason" <JC20032344@hotmail.com> wrote in message news:<eluWc.211$2F.144@trnddc05>...[color=blue]
> 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.[/color]

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::ostream', or 2) set the output stream in a
constructor.
[color=blue]
> 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?[/color]

Sure.

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

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.
[color=blue]
> 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&))[/color]

This is just complicated. Pointers to functions are often helped by
typedefs.
[color=blue]
> {
> object_ptr = obj;
> func_ptr = Display;[/color]

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.
[color=blue]
> }
> virtual void print(const string &s)
> {
> (*object_ptr.*func_ptr)(s);[/color]

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);
[color=blue]
> }
> ~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;[/color]

You should flush the stream with 'std::flush' or 'std::endl'.
[color=blue]
> }
> 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
> */[/color]

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

HTH, /david
Closed Thread