Error Handling Paradigms: Mixing Exceptions and Error Codes - c++

I'm currently developing a game engine in C++ using various pieces of middleware including OGRE (graphics), Bullet (physics), and OpenAL (sound), and I'm fairly early on in the project. It's at this point that I'm setting up my error handling mechanisms.
I plan on exposing the engine to the user by containing it within a DLL and exporting a function which will return a pointer to the main engine object. This object will contain methods with which you can access various components of the engine - most objects will be accessed via interfaces so that the user is hidden from the actual implementations.
I'm inclined to use error codes as my error reporting mechanism instead of exceptions since
Passing exceptions through the DLL link increases the complexity of error reporting, forces me to export the exception classes, etc., and
Error codes are generally more efficient, and for this reason they are common in real-time game engines.
The only issue that arises then is one with constructors - they can't return error codes. I therefore plan on using error codes for all methods, but throwing exceptions when constructors fail. Since I plan on using the factory method pattern to generate objects and pass them to user code, the exceptions would be handled internally by the engine, and the user would just get a null pointer on construction failure. I realize that you usually shouldn't mix exceptions and return codes, but the alternatives don't sound any better:
You could not do anything in the constructor and use some kind of init() method, but there goes RAII.
You could set a flag and have some kind of isOk() or isInitialized() method, but now you've introduced the possibility of some zombie state where the object exists but failed to initialize, and you might forget to check to make sure it's alive.
I'm aware of the inherent costs and benefits of both systems, and realize that it's generally a bad idea to mix the two. However, since constructors can't have some kind of return value, would it be unreasonable throw exceptions when constructors fail and use error codes elsewhere? Does anyone have a better suggestion?

I personally prefer exceptions (and have many good reasons for that). But of course throwing exceptions from DLL code to user code (and vice versa) is a bad idea. So in your situation I would use exceptions within modules (both DLLs and executable) and use error_return-based APIs for DLL exports. When using DLL's error_return-based API I would use exception-based wrappers for those error_return-ing functions.
IMO returning error indicators in any way (by return value or through reference or via per-thread error codes) havily messes the code with endless error-checking branches. My way (and my understanding of C++ way) is returning only in a case of success.

In your case, I'd say screw RAII and use Init methods. Mixing two paradigms not only decreases consistency, it also forces your Engine's consumers to implement Exception handling mechanisms when some would prefer not to.

I prefer now to only work with exceptions, but if you still need or want to use error codes with constructors a aproach that I like is to force the user to pass a parameter in constructor:
class Foo {
public:
Foo(int &errorCode) {
//our init code
rc = SOMETHING_BAD;
}
};
//on a method or function:
int errorCode;
Foo foo(errorCode);
if(errorCode != RESULT_OK)
{
//handle it
}
I think this is better than having a IsOk() method or a separated Init method, because it at least force the user to pass a variable as parameter and it is hard to forget to check errors, the downside is that sometime it is boring to declare variables just for that.
My 2 cents.

Related

C++ good error handling approach

I'm starting to write some code using C++ and I have this simple class method from a simple task manager program I'm writing as an experiment:
void Task::setText(string text)
{
if(text.length() > MIN_LENGTH)
{
this->text = text;
}
}
As you can see, this method sets the class text attribute to the one passed to the method if it's length is higher than the MIN_LENGHT variable that is defined above the code I've shown. So I have to do something if the condition does not evaluate to true for the string passed to the method.
In the C++ book I bought, error handlings are not explained, instead it just uses assert everywhere. As assert just aborts the program if the expression is false, and this is intended as input validation, I looked for a better approach.
This search led me to C++ exceptions. There it explains how to create exceptions by creating a class that inherits from exception.
Good OOP practice says that every class should be independent from the others in the program. So where should I put this exception class I create? In the same header I define my Task class in? Or should it be in task.cpp where I define every method of the class?
Maybe this is a silly question but just want to be secure and follow a good software architecture practices from the beginning.
Recommendation #1: You need to read your book completely.
It is not true that in case of every error you should throw an exception. Exception should happen something less often that every 1000 calls to your function/method. 1000 is not a magic value here, in particular case other number might be appropriate.
In other words. The first question that you need to answer: how often this error may happen. If this may happen often, then the return value (bool or enum or int) is a better approach.
If you decided to use exception, it is better to derive it from std::exception. You should place exceptions of your project in a separate file. Think about a couple of classes, maybe 3-10. It is better to place a data field inside your exception class that should explain details of what happened instead of creating hundreds of different exception classes.
the exception class can be in a separate .h .cpp file. That way you can reuse for something else.
As my own rule of thumb:
assertions are for things that should never happen but we check just to be sure 100% sure
Exceptions is for error handling things that can happen when your program is in production
C++ standard library provides many exception class that you can use. For begining, you can use them. In your case, what applies seems to be range error.
If you still want to implement your own exception class, where you declare and implement it should depend on what they code for. If they code for a class specific error, you can put them in your class file. If you have to use them from multiple files, put them in they own .cpp/.hpp couple.

How to design exception "types" in C++ [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Two anti-patterns that are incredibly common in most code bases I've worked out of are Boolean return values to indicate success/failure, and generic integral return codes to indicate more details about an error message.
Both of these are very C-like and do not fit into C++ very well in my humble opinion.
My question is in regards to best practices when it comes down to designing exceptions into your code base. In other words, what is the best way to indicate the finite possibilities for failure? For example, one of the aforementioned anti-patterns would typically have one giant enumeration with each enumeration value representing a specific kind of failure, such as FILE_DOES_NOT_EXIST or NO_PERMISSIONS. Normally these are kept as general as possible so that they can be used across multiple, unrelated domains (such as networking components and file I/O components).
A design similar to this that one might consider for exceptions is to subclass one concrete exception type from std::exception for each type of failure or thing that might go wrong. So in my previous example, we would have the following:
namespace exceptions {
class file_does_not_exist : public std::exception {};
class no_permissions : public std::exception {};
}
I think this is closer to something that "feels better", but in the end this just seems like a maintenance nightmare, especially if you have hundreds of these "error codes" to translate over into classes.
Another approach I've seen is to simply use the standard <stdexcept> classes, such as std::runtime_error and have a string with the specifics. For example:
throw std::runtime_error( "file does not exist" );
throw std::runtime_error( "no permissions" );
This design is much more maintainable but makes it difficult or unfeasible to conditionally catch either of these exceptions should they both be potentially thrown from the same core location or function call.
So what would be a good, maintainable design for exception types? My requirements are simple. I'd like to have contextual information about what happened (did I run out of memory? Do I lack filesystem permissions? Did I fail to meet the preconditions of a function call (e.g. bad parameters)?), and I'd also like to be able to act on that information accordingly. Maybe I treat all of them the same, maybe I have specific catch statements for certain failures so I can recover from them differently.
My research on this has only lead me to this question:
C++ exception class design
The user here asks a similar question that I am, and his/her code sample at the bottom is almost likable, but his/her base exception class does not follow the open/closed principle, so that wouldn't really work for me.
The C++ standard library’s exception hierarchy is IMHO pretty arbitrary and meaningless. For example, it would probably just create problems if anyone started actually using e.g. std::logic_error instead of terminating when it’s clear that the program has a Very Nasty Bug™. For as the standard puts it,
“The distinguishing characteristic of logic errors is that they are due to errors in the internal logic of the program.”
Thus, at the point where it might otherwise seem reasonable to throw a std::logic_error the program state might be unpredictably fouled up, and continued execution might put the user’s data in harm’s way.
Still, like std::string the standard exception class hierarchy has a really really practically important and useful feature, namely that it’s formally standard.
So any custom exception class should be derived indirectly or (although I would not recommend it) directly from std::exception.
Generally, when the debates about custom exception classes raged ten years ago, I recommended deriving only from std::runtime_error, and I still recommend that. It is the standard exception class that supports custom messages (the others generally have hardcoded messages that one preferably should not change, since they have value in being recognizable). And one might argue that std::runtime_error is the standard exception class that represents recoverable failures (as opposed to unrecoverable logic errors, which can’t be fixed at run time), or as the standard puts it,
“runtime errors are due to events beyond the scope of the program. They cannot be easily predicted in advance”.
Sometimes the C++ exception mechanism is used for other things, treated as just a low-level dynamic destination jump mechanism. For example, clever code can use exceptions for propagating a successful result out of a chain of recursive calls. But exception-as-failure is the most common usage, and that’s what C++ exceptions are typically optimized for, so mostly it makes sense to use std::runtime_error as root for any custom exception class hierarchy – even if that forces someone who wants to be clever, to throw a “failure”-indicating exception to indicate success…
Worth noting: there are three standard subclasses of std::runtime_error, namely std::range_error, std::overflow_error and std::underflow_error, and that contrary to what their names indicate the latter two are not required to be be generated by floating point operations and are not in practice generated by floating point operations, but are AFAIK only generated by some – surprise! – std::bitset operations. Simply put, the standard library’s exception class hierarchy seems to me to have been thrown in there just for apperance’s sake, without any real good reasons or existing practice, and even without a does-it-make-sense check. But maybe I missed out on that and if so, then I still have something new to learn about this. :-)
So, std::runtime_error it is, then.
At the top of a hierarchy of custom exception classes, with C++03 it was useful to add in the important stuff missing from C++03 standard exceptions:
Virtual clone method (especially important for passing exceptions through C code).
Virtual throwSelf method (same main reason as for cloning).
Support for chained exception messages (standardizing a format).
Support for carrying a failure cause code (like e.g. Windows or Posix error code).
Support for getting a standard message from a carried failure cause code.
C++11 added support for much of this, but except for trying out the new support for failure cause codes and messages, and noting that unfortunately it’s pretty Unix-specific and not very suitable for Windows, I haven’t yet used it. Anyway, for completeness: instead of adding cloning and virtual rethrowing (which is the best that an ordinary application programmer can do in a custom exception class hierarchy, because as an application programmer you cannot hoist a current exception object out of the storage that the implementation’s exception propagation uses), the C++11 standard adds free functions std::current_exception() and std::rethrow_exception(), and instead of support for chained exception messages it adds a mixin class std::nested_exception and free functions std::rethrow_nested and std::rethrow_if_nested.
Given the partial C++11 support for the above bullet points, a new and modern custom exception class hierarchy should better integrate with the C++11 support instead of addressing the C++03 shortcomings. Well, except for the C++11 failure code thing, which seems to be very unsuitable for Windows programming. So, at the top of the custom hierarchy, right under std::runtime_error, there will ideally be at least one general exception class, and derived from that, one exception class that supports propagation of failure codes.
Now, finally, to the gist of the question: should one now best derive a unique exception class for every possible failure cause, or at least for major failure causes?
I say no: DON’T ADD NEEDLESS COMPLEXITY.
If or where it is can be useful for a caller to distinguish a certain failure cause, a distinct exception class for that is very useful. But in most cases the only information of interest to a caller is the single fact that an exception has occurred. It is very rare that different failure causes lead to different attempted fixes.
But what about failure cause codes?
Well, when that's what an underlying API gives you, it is just added work to create corresponding exception classes. But on the other hand, when you are communicating failure up in a call chain, and the caller might need to know the exact cause, then using a code for that means the caller will have to use some nested checking and dispatch inside the catch. So these are different situations: (A) your code is the original source of a failure indication, versus (B) your code uses e.g. a Windows or Posix API function that fails and that that indicates failure cause via a failure cause code.
I have used boost::exception for a while now and I really like inserting arbitrary data into an exception.
I do this in addition to specific exception types, e.g.
#define MY_THROW(x) \
BOOST_THROW_EXCEPTION(x << errinfo_thread_id(boost::this_thread::get_id()))
class DatabaseException : public std::exception, public boost::exception { ... };
typedef boost::error_info< struct errinfo_message_, std::string > errinfo_message;
MY_THROW(DatabaseException(databaseHandle)
<< boost::errinfo_api_function("somefunction")
<< errinfo_message("somefunction failed terribly.")
);
This way you can catch specific exceptions while also providing loads of detail from the throw site (e.g., file name, line number, thread id, ...).
It also provides some pretty printing of the exception message and its details.
Most of the time I write that information in my log and abort the program, depending on the exception.
EDIT: As noted in the thread you cited, use shallow hierarchies. I use something like 3-4 exception classes that inherit directly from std::exception and boost::exception. I also put lots of details into the exceptions (e.g., the thread id).
If the error condition is something that caller of your library could have prevented by changing logic of their code then derive your exception from logic_error. Generally, caller won't be able to do simple retry if logic_error is thrown. For example, someone is calling your code such that it would cause divide by 0 then you may create custom exception,
class divide_by_zero : public logic_error {
public:
divide_by_zero(const string& message)
: logic_error(message) {
}
}
If the error condition was something that could not have been prevented by the caller then derive from runtime_error. Some of these errors might be recoverable (i.e. caller can catch exception, re-try or ignore).
class network_down : public runtime_error {
public:
network_down(const string& message)
: runtime_error(message) {
}
}
This is also the general philosophy to design exceptions in standard library. You can view the exception code for GCC here.

What is the meaning of a C++ Wrapper Class?

I have a little trouble in understanding a wrapper class. It would be great if some one could help providing apt examples.
What is a C++ Wrapper Class and what are the circumstances of writing it ?
What is it's use any way ?
Thanks.
A "wrapper class" is a de facto term meaning a class that "wraps around" a resource; i.e, that manages the resource. When people write a wrapper, then, they are doing something like this:
class int_ptr_wrapper
{
public:
int_ptr_wrapper(int value = 0) :
mInt(new int(value))
{}
// note! needs copy-constructor and copy-assignment operator!
~int_ptr_wrapper()
{
delete mInt;
}
private:
int* mInt;
};
This class manages ("wraps") a pointer to an int. All resources should be wrapped in some fashion, for cleanliness (no explicit clean up code or noise) and correctness (destructor is guaranteed to run; cannot forget to clean up, and safe with exceptions).
This pattern is called Scoped-bound Resource Management (SBRM), though a far more common (but most esoteric) name is Resource-Acquisition is Initialization (RAII). The idea is to bind a resource's clean-up to a destructor, for the reasons given above: the scope handles the rest.
Note that I said it was missing a copy-constructor and copy-assignment operator. This is due to the Rule of Three. (See linked question for detailed explanation.) The simplest way to correctly implement this rule is with the copy-and-swap idiom, explained here.
Sometimes, it's not pragmatic to write wrapper class for resource clean-up, usually when the resource is unique or used once. (Or with transactional programming.) The solution to this is called scope guard, a way of writing clean-up code inside the function that needs it.
You may find more information by searching for it in your favorite search provider (that is, Google), or going to the "primary" document here. Note that Boost provides a utility for this, as it usually does for good idioms.
A wrapper is just some smallish class whose purpose is to provide a different interface than the thing it wraps. For example, it is common to take a C API and write one or more classes that "wrap" it to provide an object-oriented interface rather than a procedural one.
You asked for circumstances of writing wrapper classes.For example, if you are in a company that makes use of different types of cameras, let us say USB, firewire etc. Each of the manufacturers will provide a different set of functions through an API to start the camera, set the parameters and read the image stream from it.
Now the programmer who builds the applications in your company need to be insulated from all the specific details in the various APIs. Now, what you can do is write a wrapper class around the APIs for each of the cameras or smarter, just one class with simple functions, wrapping around the existing code provided by the API.
For instance, we can design classes
MyUSBCameraWrapperClass,
MyFirewireCameraWrapperClass
with some member functions like
setFrameRate(int fps),
getImgFrame(*framebuffer), etc.
The programmers in your company can then use MyUSBCameraWrapperClass usbcam; usbcam.setFrameRate(30), etc. You get the point??
A wrapper class is a class that wraps a functionality with another interface.
Suppose you have the function f():
void f() { std::cout << "hello\n"; }
A simple wrapper class might be
class C {
f() { std::cout << "hello\n"; }
};
You might write a wrapper when your existing codebase expects a particular interface. This is the essence of the adapter design pattern. Or you might wrap a function in a class if you wish to maintain state for that function. Or you might wrap a function in a class' constructor or destructor if you want it to conveniently and automatically be called for you in a correct and deterministic manner. And the list goes on.
I use two kinds:
resource wrappers for function pairs provided by the OS like
UNIXs: open/close, mmap/munmap, dlopen/dlclose
Windows: CreateFile/DestroyHandle, CreateFileMapping/CloseHandle, LoadLibrary/FreeLibrary
functional wrappers for functions provided by the OS like
UNIXs: write, read, dlsym
Windows: ReadFile, WriteFile, GetProcAddress
The resource wrapper makes certain, that compiler generated code worries about the destruction of the resource created by the constructor via what is today called RAII. It is easy to combine such classes via base/member class relationships into complex classes.
In case of the creation function fails, a system error exception is thrown, providing rich error information about the error.
The functional wrapper is used instead of the plain OS function. Also in case of failure a system exception is being thrown.
This way somebody using my code doesn't need a debugger and debug code to find out what is failing in a complex environment with many libraries and processes and remote machines.
Also these wrappers provide some OS abstraction -- the code using them does not have to worry about OS differences.

C++ exception class design [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What is a good design for a set of exception classes?
I see all sorts of stuff around about what exception classes should and shouldn't do, but not a simple design which is easy to use and extend that does those things.
The exception classes shouldn't throw exceptions, since this could lead straight to the termination of the process without any chance to log the error, etc.
It needs to be possible to get a user friendly string, preferable localised to their language, so that there's something to tell them before the application terminates itself if it can't recover from an error.
It needs to be possible to add information as the stack unwinds, for example, if an XML parser fails to parse an input stream, to be able to add that the source was from a file, or over the network, etc.
Exception handlers need easy access to the information they need to handle the exception.
Write formatted exception information to a log file (in English, so no translations here).
Getting 1 and 4 to work together is the biggest issue I'm having, since any formatting and file output methods could potentially fail.
EDIT:
So having looked at exception classes in several classes, and also in the question Neil linked to, it seems to be common practice to just completely ignore item 1 (and thus the boost recommendations), which seems to be a rather bad idea to me.
Anyway, I thought I'd also post the exception class I'm thinking of using.
class Exception : public std::exception
{
public:
// Enum for each exception type, which can also be used
// to determine the exception class, useful for logging
// or other localisation methods for generating a
// message of some sort.
enum ExceptionType
{
// Shouldn't ever be thrown
UNKNOWN_EXCEPTION = 0,
// The same as above, but it has a string that
// may provide some information
UNKNOWN_EXCEPTION_STR,
// For example, file not found
FILE_OPEN_ERROR,
// Lexical cast type error
TYPE_PARSE_ERROR,
// NOTE: in many cases functions only check and
// throw this in debug
INVALID_ARG,
// An error occured while trying to parse
// data from a file
FILE_PARSE_ERROR,
}
virtual ExceptionType getExceptionType()const throw()
{
return UNKNOWN_EXCEPTION;
}
virtual const char* what()throw(){return "UNKNOWN_EXCEPTION";}
};
class FileOpenError : public Exception
{
public:
enum Reason
{
FILE_NOT_FOUND,
LOCKED,
DOES_NOT_EXIST,
ACCESS_DENIED
};
FileOpenError(Reason reason, const char *file, const char *dir)throw();
Reason getReason()const throw();
const char* getFile()const throw();
const char* getDir ()const throw();
private:
Reason reason;
static const unsigned FILE_LEN = 256;
static const unsigned DIR_LEN = 256;
char file[FILE_LEN], dir[DIR_LEN];
};
Point 1 is addressed since all strings are handled by copying to an internal, fixed size buffer (truncating if needed, but always null terminated).
Although that doesn't address point 3, however I think that point is most likely of limited use in the real world anyway, and could most likely be addressed by throwing a new exception if needed.
Use a shallow hierarchy of exception classes. Making the hierarchy too deep adds more complexity than value.
Derive your exception classes from std::exception (or one of the other standard exceptions like std::runtime_error). This allows generic exception handlers at the top level to deal with any exceptions you don't. For example, there might be an exception handler that logs errors.
If this is for a particular library or module, you might want a base specific to your module (still derived from one of the standard exception classes). Callers might decide to catch anything from your module this way.
I wouldn't make too many exception classes. You can pack a lot of detail about the exception into the class, so you don't necessarily need to make a unique exception class for each kind of error. On the other hand, you do want unique classes for errors you expect to handle. If you're making a parser, you might have a single syntax_error exception with members that describe the details of the problem rather than a bunch of specialty ones for different types of syntax errors.
The strings in the exceptions are there for debugging. You shouldn't use them in the user interface. You want to keep UI and logic as separate as possible, to enable things like translation to other languages.
Your exception classes can have extra fields with details about the problem. For example, a syntax_error exception could have the source file name, line number, etc. As much as possible, stick to basic types for these fields to reduce the chance of constructing or copying the exception to trigger another exception. For example, if you have to store a file name in the exception, you might want a plain character array of fixed length, rather than a std::string. Typical implementations of std::exception dynamically allocate the reason string using malloc. If the malloc fails, they will sacrifice the reason string rather than throw a nested exception or crashing.
Exceptions in C++ should be for "exceptional" conditions. So the parsing examples might not be good ones. A syntax error encountered while parsing a file might not be special enough to warrant being handled by exceptions. I'd say something is exceptional if the program probably cannot continue unless the condition is explicitly handled. Thus, most memory allocation failures are exceptional, but bad input from a user probably isn't.
Use virtual inheritance. This insight is due to Andrew Koenig. Using virtual inheritance from your exception's base class(es) prevents ambiguity problems at the catch-site in case someone throws an exception derived from multiple bases which have a base class in common.
Other equally useful advice on the boost site
2: No you should not mix user interface (=localized messages) with program logic.
Communication to the user should be done at an outer level when the application
realises that it cannot handle the issue. Most of the information in an
exception is too much of an implementation detail to show a user anyway.
3: Use boost.exception for this
5: No dont do this. See 2. The decision to log should always be at the error handling site.
Dont use only one type of exception. Use enough types so the application can
use a separate catch handler for each type of error recovery needed
Not directly related to the design of an exception class hierarchy, but important (and related to using those exceptions) is that you should generally throw by value and catch by reference.
This avoids problems related to managing the memory of the thrown exception (if you threw pointers) and with the potential for object slicing (if you catch exceptions by value).
Since std::nested_exception and std::throw_with_nested have become available with C++11, I would like to point to answers on StackOverflow here and here
Those answers describe how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
The exception design there, in my opinion, also suggests to not create exception class hierarchies, but to only create a single exception class per library (as already pointed out in an answer to this question).
A good design is not to create a set of exception classes -
just create one per library, based on std::exception.
Adding information is fairly easy:
try {
...
}
catch( const MyEx & ex ) {
throw MyEx( ex.what() + " more local info here" );
}
And exception handlers have the information they need because they are exception handlers - only the functions in the try blocks can cause exceptions, so the handlers only need to consider those errors. And not you should not really be using exceptions for general error handling.
Basically, exceptions should be as simple as possible - a bit like logfiles, which which they should have no direct connection.
This has been asked before, I think, but I can't find it right now.

What's the proper "C++ way" to do global variables?

I have a main application class, which contains a logger, plus some general app configurations, etc.
Now I will display a lot of GUI windows and so on (that will use the logger and configs), and I don't want to pass the logger and configurations to every single constructor.
I have seen some variants, like declaring the main class extern everywhere, but that doesn't feel very object oriented. What is the "standard" C++ way to make elements in the main class accessible to all (or most) other classes?
Use the singleton design pattern.
Basically you return a static instance of an object and use that for all of your work.
Please see this link about how to use a singleton and also this stackoverflow link about when you should not use it
Warning: The singleton pattern involves promoting global state. Global state is bad for many reasons.
For example: unit testing.
It is not so bad idea to pass the logger and config to all the constructors if your logger and config is abstract enough.
Singleton can be a problem in the future. But it seams like a right choice in the project begin. Your choice. If your project is small enough - go with singleton. If not - dependency injection.
Why not use the system that's already in place? That is, redirect std::clog to output to a file and write to std::clog.
std::fstream *f = new std::fstream("./my_logfile.log")
std::clog.rdbuf(f->rdbuf());
std::clog << "Line of log information" << std::endl;
I'd agree with some kind of singleton approach. You definitely don't want to pass logger objects around all over the place. That will get very boring very quickly, and IMHO is a worse design than just having a plain global object.
A good test of whether you've got a good solution is the steps required to get the logging working in a function that needs it.
If you have to do much more than
#include "Logger.h"
...
void SomeFunction()
{
...
LOGERROR << "SomeFunction is broken";
...
}
...
then you are wasting effort.
Logging falls under the realm of 'separation of concern' as in aspect orient programming
Generally logging is not a function or concern of an object (for example, it does not change the state of the object; it is merely a mechanism for observing/recording the state, and the output is essentially disposable in most contexts)
It is an ephemeral and often optional side function that does not contribute to the operation of a class.
An object's method may perform logging, but the logging may be done there because it is a convenient place to do it or that point in the code execution stream is where one desires the state to be recorded.
Because C++ does not provide facilities for defining aspects, I tend to simply keep essentially external ephemeral objects like loggers global and wrap them in a namespace to sort of contain them. Namespaces are not intended for containment so this is kind of ugly, but for for lack of anything else it is convenient and is far less ugly and inconvienent than passing loggers in formal parameters or referencing them in all the objects you want to log. This also makes it easier to remove the logger if at some point I decide I no longer need the logger (I.e. if it was only used for debugging).
Don't know if this is helpful in your situation or not, but in MFC, there was/is an application class.
I use to throw things like this into that class.
I assume you are not using MFC, but if you have an application class or something similar, this might be helpful.
Why not use log4cxx?
Such problems are solved long ago and widely used by many.
Unless you're building some very special logging system of your own... In such case, I'd use Factory pattern which would create loggers for anyone interested (or giving away existing instance if it's singleton). Other classes would use factory to obtain the logger. Passing loggers in constructor parameters is a bad idea, because it couples your class with logger.
Why has no one thought of heritage and polymorphism? You could also use an abstract factory with that singleton ;)
Simply pass your main class into the constructor of the other classes that you want to have access to "everything"
Then you can provide access to the logger etc. via member properties.
(Forgive my C++ syntax, this is just a made-up language called "C++ confused by VB")
e.g.
Class App {
Private m_logger;
Private m_config;
Public logger() {
return m_logger;
}
Public config() {
return m_config
}
}
Class Window1 {
New( anApp ) {
}
....
}
I guess Service Locator will do. That you'll have to either pass around in constructors, or have a globally accessible static member function in some well-known location. The former option is much more preferable.
I would avoid the singleton pattern.
Too many problems when it comes to testing and all that (see What is so bad about singletons?)
Personally I would pass the logger etc into the constructor. Alternatively you can use a factory to create/pass a reference to the resource.