通常情况下,您可以在现有接口的末尾添加新方法而不会破坏兼容性。但正如您所阅读的那样,有些微妙的情况可能会导致破坏,特别是当已经使用多重继承时。正确的解决方案是为新方法声明一个新的接口,不要改动您现有的接口。然后让您现有的对象实现这两个接口或使用继承让新接口从旧接口继承。例如,如果以下是我们的原始代码(为了简洁起见,我假装没有使用IDL文件)。
class IPublicInterface : public IUnknown
{
public:
virtual void M1() = 0;
virtual void M2() = 0;
}
class MyPublicClass : IPublicInterface
{
public:
void M1();
void M2();
HRESULT QueryInterface(...);
ULONG AddRef();
ULONG Release();
};
现在假设我们想要向这个对象添加一个名为M3的新方法,而不会破坏现有接口和对象的用户。正确的解决方案是添加一个新接口。为了方便起见,它可以从原始接口继承。
class IPublicInterface2 : public IPublicInterface
{
public:
virtual void M3() = 0;
};
现在修改该类,使其继承自这个新的派生接口:
class MyPublicClass : public IPublicInterface2
{
public:
void M1();
void M2();
void M3();
HRESULT QueryInterface(...);
ULONG AddRef();
ULONG Release();
};
更新QueryInterface方法,支持对IPublicInterface原始UUID和IPublicInterface2的调用。
HRESULT MyPublicClass::QueryInterface(GUID& iid, void** ppv)
{
if ((iid == uuidof(IPublicInterface) || (iid == uuidof(IUnknown))
{
*ppv = (IPublicInterface*)this;
AddRef();
return S_OK;
}
else if (iid == uuidof(IPublicInterface2)
{
*ppv = (IPublicInterface2*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
另外,IPublicInterface2无需继承原始IPublicInterface。在这种情况下,实现类从两个接口继承。在QueryInterface实现中,您需要一致地处理对IUnknown的可能模糊转换。