0

Possible Duplicate:
pure virtual function and abstract class

I have a class and I want to create a virtual function that will be used to print debug information. Any class that inherits this class will have to implement this virtual function. This way different classes could print the debug messages to different output devices such as std::cout, labels, files etc.

The base class won't be aware of the messages destination. But I don't know the best way to do this. I'm thinking of using something like printf() which can print an arbitrary number of parameters. But I don't know what that would be accomplished. Any ideas?

Community
  • 1
  • 1
Dgdiniz
  • 23
  • 3
  • 1
    Try Google [glog](http://code.google.com/p/google-glog/) – Captain Obvlious Jul 27 '12 at 22:33
  • 1
    Welcome to Stack Overflow. I'm afraid I don't understand your question. You know how to write virtual functions *in general*, right? So what's the trouble with this? How is the virtualness even relevant? Would you know how to define your function if it *weren't* virtual? – Rob Kennedy Jul 27 '12 at 22:44
  • Hi, I'm thinking in creating a function like printf, where you can print messages like print("Message %s, %d", "debug", 1), so the classes that inherits this base class could put the message in any place, like files, some visual widget, etc. – Dgdiniz Jul 27 '12 at 22:45
  • I dont want to pass only a string already formated as parameter. I want to create a funcion more flexible. – Dgdiniz Jul 27 '12 at 22:50
  • 1
    Inheritance sort of does the opposite thing: It gives you *different* implementations under a common interface. By the sound of it, you want a *common* facility available from different parts of your code. A global variable might be more appropriate for that... – Kerrek SB Jul 27 '12 at 22:50

5 Answers5

2

There is a disadvantage to the approach that you propose. Every derived class will have to implement a printf like facility themselves. That doesn't seem like a very productive activity, and it would make the base class very annoying to use.

It may be less burdensome, code wise, to have the base class require the derived classes provide a debug ostream. Or, you could default to cerr.

class Base {
protected:
    virtual std::ostream & debug_stream () const { return std::cerr; }
    //...
};

Then, an external user of Base can poke info into the debug_stream.

If you insist on printf style syntax, the interface could return a FILE * instead:

class Base {
protected:
    virtual FILE * debug_file () const { return stderr; }
    //...
};

So, for example, a derived class could do this:

class Derived : public Base {
    static std::ofstream dbgstream;
    std::ostream & debug_stream () const { return dbgstream; }
    //...
};

std::ofstream Derived::dbgstream("/tmp/derived.dbg");

Then if one has proper access to the base class interface,

void foo (Base *b) {
    //...do something with b
    b->debug_stream()
        << __FILE__ << ":" << __LINE__ << " foo did something"
        << std::endl;
    //...
}
jxh
  • 69,070
  • 8
  • 110
  • 193
  • Seems to be a better solution than the string method. Could you put some code showing how to implement and use this function? Thanks – Dgdiniz Jul 27 '12 at 23:15
  • You can also add this null stream implementation so that classes can be configured to log to the bitbucket: http://stackoverflow.com/a/760353/12711 – Michael Burr Jul 27 '12 at 23:21
  • @MichaelBurr: That looked nice, but all the arguments would still be evaluated. To disable debugging more efficiently, the code should be disabled somehow. See for example http://stackoverflow.com/a/11480580/315052 – jxh Jul 28 '12 at 07:05
0

I would just do this

class Base
{
   virtual int debugfn(const std::string& msg) const = 0;
};

I.e., don't mix the functionality of printf (producing a formatted string and sending it to stdout) with the debugging function. Let it take as its argument a string that is already complete, and let the derived classes decide what to do with it. The int can be an error code if desired, otherwise just return void.

Matt Phillips
  • 9,465
  • 8
  • 44
  • 75
  • It's ok, but this way you will have a lot of extra code to format the string before calling the debugfn. I want a more flaxible way, like the printf example. – Dgdiniz Jul 27 '12 at 22:52
0

I would do something like this:

class Base 
{ 
protected:
   virtual int doDebug(const std::string& Msg) const = 0; 

public:
   int Debug(const char* MsgFmt, ...) const; 
}; 

int Base::Debug(const char* MsgFmt, ...) const
{
    std::string sMsg;
    va_list args;

    va_start(args, MsgFmt);
    int len = vsnprintf(NULL, 0, MsgFmt, args);
    if (len > 0)
    {
        sMsg.resize(len);
        vsnprintf(&sMsg[0], len + 1, MsgFmt, args);
    }
    va_end(args);

    return doDebug(sMsg); 
}

That way, you still provide the caller with flexible formatting, but the derived classes do not have to worry about that because they are given only pre-formatted text.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Yes, this is exactly what I'm looking for. Now I can print the logs like a printf, and the debug messages will be put where I want, without the base class being aware of the destination :D Thank you – Dgdiniz Jul 30 '12 at 19:40
0

The basic idea here is to use a protected virtual function that takes a string as the error/log/debug-message to be printed / logged. Then, your base class exposes a non-virtual function (or set of functions) to construct the string that will be fed to the protected virtual function. To actually create the string, you can use one of many ways, in the style of printf (with varargs or variadic templates (C++11)), or in the style of standard iostreams. Here is one solution in the latter category:

class BaseDebugOutput {
  protected:
    virtual void printMessage(const std::string& aMsg) = 0;

  private:
    std::stringstream temp_stream;
  public:
    virtual ~BaseDebugOutput() { };

    // One << operator for any type.
    template <typename T>
    BaseDebugOutput& operator<<(const T& value) {
      temp_stream << value;
      return *this;
    };

    typedef std::basic_ostream< std::stringstream::char_type,
                                std::stringstream::traits_type >& 
              (*ostream_function_ptr)(
                std::basic_ostream< std::stringstream::char_type,
                                    std::stringstream::traits_type >&);

    // One << operator for things like std::endl.
    BaseDebugOutput& operator<<(ostream_function_ptr p) {
      if(p == ostream_function_ptr(std::endl)) {
        // if the user outputted an end-line, then print the entry:
        temp_stream << std::endl;
        std::string temp_msg;
        std::getline(temp_stream,temp_msg);
        // call the protected virtual function:
        printMessage(temp_msg);
      } else {
        temp_stream << p;
      };
      return *this;
    };
};

An example derived class would be:

class CErrDebugOutput : public BaseDebugOutput {
  protected:
    virtual void printMessage(const std::string& aMsg) {
      std::cerr << "Error reported with message: '" << aMsg << "'." << std::endl;
    };
};

And the use-case would look like this:

int main() {
  BaseDebugOutput* debug_output = new CErrDebugOutput;

  (*debug_output) << "The answer is: " << 42 << "!" << std::endl;

  delete debug_output;
  return;
};

One advantage of the above setup is that you can insert almost anything you want in addition to the error message, such as a time-stamp for example, or just adding the "Error: " string or whatever so that you don't have to repeat that all the time at the points where you issue the messages (call-site).

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
0

I might not have understood the question, because the simplest thing that comes to mind has not been offered in all the other answers... If the intention is providing a single entry point for all the hierarchy to print information, then this is the simplest approach:

class base {
public:
   virtual std::ostream& print( std::ostream& /*...*/ ) const = 0;
};
std::ostream& operator<<( std::ostream& o, base const & b ) {
   return b.print( o );
}

The comment /*...*/ is there because, unlike operator<< the signature is not fixed, so you could pass extra arguments to control the formatting (say, bool single_line, int indent --if !single_line to insert leading spaces, int verbosity to control whether only the public state of the object is to be printed or also auxiliary data...) to produce richer output.

With a single implementation (and a forwarding function) you get printing of the objects to a stream and a way of generating logs with the state of your program for debugging.

If on the other hand what you mean is a solution for derived classes to print debug messages regarding their state at different points in time, then you cannot really do that polymorphically, as the decision to log messages and when should be taken by the derived types. In that case, just pull a logging library and use it. Common logging libraries have very little cost at runtime if the log level is lower than the type of messages (i.e. if you configure to log only warning, the cost of the debug logs (that will not be generated) is very small.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489