I want to add a new method to a COM interface with all the existing one unchanged, will this break its compatibility for the consumer before this update?
It depends: if this is an internal unpublished interface, you are free to change it at will so long as you control all the code that interacts with that interface.
Once published, however, the rules are strict: every interface has its own IID. You change that interface in any way - by modifying, adding or removing methods - it's a whole new interface, and requires a new IID.
However: COM does doesn't care how that new interface is implemented: so you can have your class implement it as a derivation of the old interface that just adds a new method, and have your implementation class implement the derivation, so long as QI returns a suitable interface when asked for either the old or new interface.
For example:
class IInterfaceOriginal: public IUnknown
{
public:
...
// lots of methods
...
};
class IInterfaceUpdated: public IInterfaceOriginal
{
public:
// Add just one additional method
STDMETHOD(AdditionalMethod)(...) = 0;
};
class CImplementation: IInterfaceNew // this was IInterfaceOld
{
// Also add implemention of AdditionalMethod somewhere here...
HRESULT STDMETHODCALLETYPE QueryInterface( REFIID riid, void **ppvObject )
{
*ppvObject = NULL;
if(riid == __uuidof(IUnknown)
|| riid == __uuidof(IInterfaceOriginal)
|| riid == __uuidof(IInterfaceUpdated)) // This is added
{
// Return a IInterfaceUpdated in response to a QI for either of IUnknown,
// or the old or new interface. This works because in C++, any IInterfaceUpdaed
// is also both of those two other interfaces.
*ppvObject = static_cast<IInterfaceUpdated*>(this);
}
else
return E_UNKNOWN;
return ((IUnknown*)*ppvObject)->AddRef();
}
...
}
So, while you are technically "adding another interface", you're actually adding little code here: just defining a new interface that derived from the old one, changing the interface your class implements to the new one (and adding the implementation for the new method), and finally updating QI to support both the old and new methods - returning the same interface for both (and for IUnknown too).
It would certainly break derived interfaces, so it should not be done even if it appears to work.
Instead, derive a new interface containing the additional method(s), and have clients that require the additional functionality QI for the new IID.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With