I have a class with a static member:
class MyClass
{
public:
static const SomeOtherClass myVariable;
};
Which I initialize in the CPP file like so:
const SomeOtherClass MyClass::myVariable(SomeFunction());
The problem is, SomeFunction()
reads a value from the registry. If that registry key doesn't exist, it throws an exception. This causes my program to explode without giving the user any useful output... is there some way I can catch the exception so I can log it?
I don't like
static
data members much, the problem of initialization being foremost.Whenever I have to do significant processing, I cheat and use a local
static
instead:This way, the exception will be throw only on first use, and yet the object will be
const
.This is quite a powerful idiom to delay execution. It had a little overhead (basically the compiler checks a flag each time it enters the method), but better worry about correctness first ;)
If this is called from multiple threads:
boost::once
in theBoost.Threads
libraryconst
, you may not care if it's initialized multiple times, unlesssomeOtherFunction
does not support parallel execution (beware of resources)Guideline: only use
static
orglobal
variables instantiation for simple objects (that cannot throw), otherwise uselocal static
variables to delay execution until you can catch the resulting exceptions.You can wrap the function inside another function that catches the exception and alerts the user of the problem (or creates the key with a safe default value)
Perhaps the best thing to do would be to add the registry key to a list instead of looking it up, then as soon as main() is entered, go through and look up all of the keys in the list. I don't want to be preachy but situations like this are exactly why it's generally a bad idea to do significant processing before main() is entered.
Sure -- wrap
SomeFunction()
in a function like:Then upon entry to main, you'll want to check for
static_error != 0
and print an appropriate error message if needed (unfortunately, you can't know ifstd::cerr
exists yet in your exception handler, so if you want to print from there, you'll have to do something like C FILE*-based output).You could make a wrapper class that delays construction of the object. Then when its first used, it will throw where ever its first used, if the constructor throws.
This has the benefit of not having alot of code run before main() is called, and if you don't ever actually use the global object it won't ever be initialized.
The code:
Prints out: