You need something to catch errors transparently and do some recovery action, it sounds like a job for a proxy object.
Bascially your current interface doesn't quite cut it as far as transparency of recovery goes. The idea here is that you implement you interface again in a containing (proxy) object that passes calls through to the real object handling any errors that come out, all without the caller knowing.
Say you have an interface A, it's got one member, f:
class A
{
public:
virtual bool f() = 0;
};
The idea is that f does something useful, returning false if something breaks. This is the equivalent of your COM interface.
You've implemented this interface in B...
class B : public A
{
public:
virtual bool f();
};
This is the equivalent of your CoClass. The problem is that f's returning false a bit too often and your code is full of chaff like:
void do_something( A *ptr )
{
if( !ptr && !ptr->f() )
{
do_remedial_action();
}
}
It's okay with one function, but wait until you implement some more on your interface!
So how can you hide the whole problem?
1. Declare a new class, a proxy, which implements A:
class recoverable_proxy_for_A : public A
{
public:
virtual bool f()
{
return false;
}
};
Doesn't do a lot does it? Hang in there!
2. Add a constructor for recoverable_proxy_for_A which takes an instance of an object implementing A:
class recoverable_proxy_for_A : public A
{
public:
recoverable_proxy_for_A ( A *to_be_proxied )
: proxied_( to_be_proxied )
virtual bool f()
{
return false;
}
private:
A *proxied_;
};
3. Implement recoverable_proxy_for_A by calling through to the contained A:
class recoverable_proxy_for_A : public A
{
public:
recoverable_proxy_for_A ( A *to_be_proxied )
: proxied_( to_be_proxied )
virtual bool f()
{
return proxied_->f();
}
private:
A *proxied_;
};
4. Finally add the magic thing bit in... Handle the error in the call to recoverable_proxy_for_A::f:
class recoverable_proxy_for_A : public A
{
public:
recoverable_proxy_for_A ( A *to_be_proxied )
: proxied_( to_be_proxied )
virtual bool f()
{
if( !proxied_->f() )
{
do_remedial_action();
return proxied_->f(); }
return true;
}
private:
A *proxied_;
};
The you can replace every use of instance of something implementing A in your code with recoverable_proxy_for_A and your error checking happens automagically.