基类更改后重新编译
recompile after base class change
特别是,大多数C++实现的工作方式意味着基类大小的更改需要重新编译所有派生类。
这句话来自stroustrup的书。所以,如果基类在.so
文件中,并且我们只更改了一个成员函数实现,那么这是否意味着我们不必重新编译链接到该共享对象的程序?
从形式上讲,如果不重新编译,就违反了一个定义规则,并得到未定义的行为。
实际上,只要您修改的成员函数没有在任何地方内联,并且您没有更改签名,就可能保持二进制兼容性。在大多数平台上。如果幸运的话,您的平台文档提供了这样的保证。
我相信你的理解是正确的。仅仅更改成员函数的主体并不会更改该对象的实例所需的空间量。代码没有存储在对象实例中;只有数据是
编译类时,对成员数据字段的引用只是从该对象数据开头的偏移量。派生类的数据通常放在基类的数据之后。因此,如果向基类添加一个字段,则派生类数据的正确偏移量都会发生变化,这意味着基类需要重新编译,以指向新的(正确的)偏移量。
之前
class Foo {
int a; // offset 0 (assuming no vtable)
}
class Bar : public Foo {
int b; // offset 4
}
Bar bar; bar.b = 7; // sets the 32-bit value at this+4 to 7
之后
class Foo {
int a; // offset 0
int c; // offset 4
}
class Bar : public Foo {
int b; // offset 8
}
Bar b; bar.b = 7; // Without recompiling: sets the 32-bit value at this+4
// which is actually where Foo.a is stored!
// With recompiling: sets the 32-bit value at this+8
如果只是实现,它应该可以正常工作。这就是Windows DLL的全部概念。添加或删除接口不会改变类的大小(除非你引入了一个新的虚拟函数),但在很大程度上可以改变内存中的函数布局。因此,如果使用新函数,则需要重新编译。另一方面,由于对头文件进行了简单的修改,大多数现代编译器都足够聪明,能够识别出相关的更改。
相关文章:
- 使用 MINGW gcc 编译时,不会为 std::string 调用重载的新运算符
- 如何编译:Mac上的Synergy(2017年的新工具链)
- 如何编译和运行一个新的 C++ Actor 框架项目?
- C++编译新的警告过滤器
- 每次都构建(make)lib,只有在lib较新时才重新编译项目
- 如何创建指向派生类的新指针,该派生类在C++编译时未知
- 如何在不退出和失去断点的情况下重新加载重新编译的二进制文件
- 在编译时将整数和分数部分宏组合成一个新的宏或双精度
- C++运算符新重载、编译错误
- 在新OSX上编译旧碳应用
- 为什么G 5.4不能编译此编译时质数代码
- 代码块在尝试编译或创建新文件时出现"An assertion failed!"错误
- 在新的Visual Studio项目中包含任何Eigen 3.3.1文件将无法编译
- RCpp:如何在不重新启动R的情况下重新加载重新编译的C++代码
- 新安装的MinGW问题与编译和可执行文件
- 为什么要编译?(编译是否忽略未包含的 h 文件?
- 高级C和C++编译:无法编译书中提到的示例程序
- 在不同的编译单元中使用不同的编译标志编译相同的头
- 在cygwin中编译新的mingw二进制文件
- 使用boost库编译预编译头文件需要很长时间