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

Discussion in 'C++' started by Jason, Aug 23, 2004.

  1. Jason

    Jason Guest

    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 */
    Jason, Aug 23, 2004
    #1
    1. Advertising

  2. Jason

    Mike Wahler Guest

    "Jason" <> wrote in message
    news:eluWc.211$2F.144@trnddc05...
    > 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
    Mike Wahler, Aug 24, 2004
    #2
    1. Advertising

  3. Jason

    David Rubin Guest

    "Jason" <> wrote in message news:<eluWc.211$2F.144@trnddc05>...
    > 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
    David Rubin, Aug 24, 2004
    #3
  4. Jason

    Jason Guest

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



    "David Rubin" <> wrote in message
    news:...
    > "Jason" <> wrote in message

    news:<eluWc.211$2F.144@trnddc05>...
    > > 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
    Jason, Aug 25, 2004
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ViperDK

    The right way to Encode html output

    ViperDK, Jul 17, 2003, in forum: ASP .Net
    Replies:
    2
    Views:
    680
    Nicole Calinoiu
    Jul 22, 2003
  2. Dav Tan
    Replies:
    4
    Views:
    9,671
    Steven Cheng[MSFT]
    Apr 28, 2006
  3. Paul
    Replies:
    1
    Views:
    424
  4. jmr
    Replies:
    2
    Views:
    320
  5. Sal
    Replies:
    1
    Views:
    374
Loading...

Share This Page