我在理解关于内联和客户二进制兼容性方面的句子时遇到了麻烦,能有人解释一下吗?
C++ FAQ Cline, Lomow:
当编译器合成复制构造函数时,它会使它们变成内联函数。如果你的类暴露给了客户(例如,如果你的客户 #include 你的头文件而不仅仅是使用从你的类创建的可执行文件),你的内联代码将被复制到你的客户可执行文件中。如果你的客户要在你的头文件发布版本之间保持二进制兼容性,则不应更改对客户可见的内联函数。因此,您需要一个显式的、非内联版本的复制构造函数,以便客户可以直接使用。
我在理解关于内联和客户二进制兼容性方面的句子时遇到了麻烦,能有人解释一下吗?
C++ FAQ Cline, Lomow:
当编译器合成复制构造函数时,它会使它们变成内联函数。如果你的类暴露给了客户(例如,如果你的客户 #include 你的头文件而不仅仅是使用从你的类创建的可执行文件),你的内联代码将被复制到你的客户可执行文件中。如果你的客户要在你的头文件发布版本之间保持二进制兼容性,则不应更改对客户可见的内联函数。因此,您需要一个显式的、非内联版本的复制构造函数,以便客户可以直接使用。
liba
作为共享库。如果liba
在其公开的类中的某个方法中存在错误,则可以更改内部实现并重新编译共享库,程序可以使用该liba
的新二进制版本而无需重新编译自身。但是,如果liba
更改了公共契约,例如内联方法的实现或将内联方法移动到外部声明,则会破坏应用程序二进制接口(ABI),消费程序必须重新编译以使用liba
的新二进制版本。考虑以下编译为静态库的代码:
// lib.hpp
class
t_Something
{
private: ::std::string foo;
public: void
Do_SomethingUseful(void);
};
// lib.cpp
void t_Something::
Do_SomethingUseful(void)
{
....
}
// user_project.cpp
int
main()
{
t_Something something;
something.Do_SomethingUseful();
t_Something something_else = something;
}
t_Something
类的字段发生变化时,例如添加了一个新字段,我们就会陷入这样一种情况:所有用户代码都必须重新编译。基本上,编译器隐式生成的构造函数从我们的静态库“泄漏”到用户代码中。t_Something
的user_project.cpp
和其他文件必须重新编译,而如果构造函数被明确定义并在lib.cpp
中实现,则不需要这样做。 - user7860670lib.cpp
中取出,并将其完全内联到user_project.cpp
的main()
中。 - Fire Lancer我认为我理解了这段话的意思。但我并不是在支持它。
我相信,他们描述的情况是当你正在开发一个库并以头文件和预编译二进制库的形式提供给客户时。在客户完成初始构建后,他们应该能够用新的二进制部分替换旧的而无需重新编译他们的应用程序 - 只需要重新链接即可。唯一实现这一点的方法是保证头文件是不可变的,即在版本之间不会更改。
我猜这个想法来自于98年的构建系统还不够智能,无法检测头文件的更改并触发受影响源文件的重新编译。
现在这些都已经过时了,事实上,这与潮流背道而驰 - 因为大量的库实际上试图成为仅包含头文件的库,出于多种原因。
make
诞生于1976年。) - molbdnilo