【问题标题】:C++ shared libraries with inheritance具有继承的 C++ 共享库
【发布时间】:2012-01-23 19:03:18
【问题描述】:

我有一个带有基类 (MyClassA) 的库 (a.so)。另一个库(b.so)有一个类 MyClassB,它继承自 MyClassA(在 a.so 中)。我编译了在 a.so 中隔离的 MyClassA.h 和 MyClassA.cpp。 MyClassB.h 和 MyClassB.cpp 是单独编译的(引用 MyClassA.h 但未将 MyClassA.h 添加到 b.so)。然后我将 b.so 链接到 a.so。

总结一下:

  1. a.so 包含 MyClassA.h 和 MyClassA.cpp
  2. b.so 包含 MyClassB.h 和 MyClassB.cpp
  3. b.so 链接到 a.so

当我尝试编译时,我收到了许多由 b.so 引起的 MyClassA 引用错误。

当我编译 b.so 并将 MyClass.h 添加到它时,库编译并运行没有任何错误。因此:

  1. a.so 包含 MyClassA.h 和 MyClassA.cpp
  2. b.so 包含 MyClassB.h、MyClassB.cpp 和 MyClassA.h
  3. b.so 链接到 a.so

是否可以在 C++ 中使用我的第一个选项,或者是否需要始终在子类库中包含基本头文件?

【问题讨论】:

  • 作为第一个选项应该可以工作,我们需要查看更多错误和代码,尤其是标题及其包含的内容

标签: c++ inheritance linker shared


【解决方案1】:

如果你从ClassA 派生ClassB,你应该有你的ClassA定义,在派生时,不仅仅是声明引用)。这就是为什么你必须包含 ClassA 头文件。

但是如果你在cpp文件中实现了ClassA函数,而不是在头文件中,ClassA的实际代码将在a.so中,所以,包含ClassA头文件是问题不大。

【讨论】:

  • 唯一的问题是a.so中有很多头文件,我在b.so中使用。当我将标头添加到 b.so 时,b.so 的大小会急剧增加(即使只包含标头而不包含 cpp 文件)。我想知道是否有办法解决这个问题,这样我就可以保持 b.so 非常小。毕竟headers已经在a.so中了
  • 检查您的标头是否包含 code,例如函数 defenitions(不是 declarations),或者可能是一些模板用法,您可以尝试使用pimplfacade 模式来减小公共标头大小
  • 我的基类头文件中有很多纯虚函数减速,没有实现。这就是标题如此之大的原因。如果我有 50 个从 a.so 中的类继承的子库,那么来自 a.so 中的类的标头数据(比如说 100kb)在 50 个子库中的每一个中都会重复。那是 50x100kb = 几乎 5mb 的重复标头实际上已经在 a.so 中
  • 嘿,你不能这样算。这 100kb 的大部分可能是运行时依赖项,好吧,如果你写 'hello world' 你可以得到 50kb,但这意味着要注意。
  • 乔,知道这一点。只是想知道是否有一个技巧告诉 b.so 不要直接包含标头,而是在运行时自动从 a.so 中提取它们?
【解决方案2】:

所有派生类必须在编译时#include 基类声明。基类实现必须在链接时已知。

在你的情况下:

  1. a.so 包含 MyClassA.h 和 MyClassA.cpp
  2. b.so 包含 MyClassB.h 和 MyClassB.cpp 但 MyClassB.h `#include "MyClassA.h"
  3. b.so 链接 a.so 使用:

g++ -o b.so -la

【讨论】:

  • 正是我所做的。 #include "MyClassA.h" 在标题 MyClassB 中。那不是问题。问题是我实际上必须在 b.so 中包含 MyClassA.h。这大大增加了库的大小。我认为链接器(编译器)会在构建时查看头文件,但我不必实际将 MyClassA.h 添加到 b.so。当我这样做时,会出现引用错误。
  • 真的,你不需要在 b.so 中包含 MyClassA.h。向我们展示 MyclassA.h 和 MyClassB.h 以及编译和链接命令。
  • 我不包含它,编译器包含它。我检查过:如果我在 MyClassA 的头文件中添加一些字符串并编译 MyClassB (b.so),那么 b.so 的大小会增加。所以编译器会自动将 MyClassA.h 拉到 b.so。我目前正在使用 CMake,忙着用普通的 g++ 编译创建一个简单的例子
  • 如果上传了一个测试示例。如果取消注释 MyClassA.h 中的第 13 行,liba.so 和 libb.so 的大小都会增加。我对 liba.so 大小的增加感到满意,但我希望 libb.so 的大小保持不变,无论 MyClassA.h 发生什么变化。
【解决方案3】:

如果class B 是从class A 派生的,则必须包含class A 头文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    相关资源
    最近更新 更多