我曾认为,每当您进行以下操作之一时:
- 添加一个新的公共虚拟方法
virtual void aMethod();
- 添加一个新的公共非虚拟方法
void aMethod();
- 从接口实现一个公共纯虚拟方法
virtual void aMethod override;
实际上会破坏二进制兼容性,这意味着如果一个项目建立在以前版本的 DLL 上,它将无法加载现在有新方法的 DLL。
根据我使用 Visual Studio 2012 进行的测试,这些操作都不会造成任何破坏。Dependency Walker 没有报告错误,我的测试应用程序也能调用适当的方法。
DLL:
class EXPORT_LIB MyClass {
public:
void saySomething();
}
可执行文件:
int _tmain(int argc, _TCHAR* argv[])
{
MyClass wTest;
wTest.saySomething();
return 0;
}
我发现的唯一未定义行为是,如果MyClass正在实现一个纯虚拟接口,并且从我的可执行文件中调用其中一个纯虚拟方法,然后在使用的那个方法之前,我添加了一个新的纯虚拟方法。在这种情况下,Dependency Walker没有报告任何错误,但在运行时,它实际上调用了错误的方法。
class IMyInterface {
public:
virtual void foo();
}
在可执行文件中。IMyInterface* wTest = new MyClass();
wTest->foo();
然后我可以在不重新构建可执行文件的情况下更改界面。
class IMyInterface {
public:
virtual void bar();
virtual void foo();
}
现在它正在安静地调用bar()
而不是foo()
。
我所有的三个假设都是安全的吗?
编辑:
这样做
class EXPORT_LIB MyClass {
public:
virtual void saySomething();
}
执行
MyClass wTest;
wTest.saySomething();
然后使用以下内容重新构建DLL:
class EXPORT_LIB MyClass {
public:
virtual void saySomething2();
virtual void saySomething();
virtual void saySomething3();
}
调用适当的saySomething()
函数