链接自注册的抽象工厂
linking a self-registering, abstract factory
我一直在使用并测试一个基于这里描述的自注册抽象工厂:
https://stackoverflow.com/a/582456
在我所有的测试用例中,它就像一个魅力,并提供我想要的功能和重用。
在我的项目中使用 cmake 在这个工厂中链接非常棘手(尽管它似乎更像是一个 ar 问题)。
我有相同的base.hpp,derivedb.hpp/cpp,以及链接到示例的等效deriveda.hpp/cpp。 总的来说,我只是实例化工厂并调用 createInstance() 两次,一次是 "DerivedA" 和 "DerivedB"。
由以下行创建的可执行文件:
g++ -o testFactory main.cpp derivedb.o deriveda.o
按预期工作。 将我的派生类移动到库中(使用 cmake,但我也单独用 ar 测试过),然后链接失败:
ar cr libbase.a deriveda.o derivedb.o
g++ -o testFactory libbase.a main.cpp
只调用第一个静态实例化(来自 derivedA.cpp),从不调用第二个静态实例化,即
// deriveda.cpp (if listed first in the "ar" line, this gets called)
DerivedRegister<DerivedA> DerivedA::reg("DerivedA");
// derivedb.cpp (if listed second in the "ar" line, this does not get called)
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
请注意,在 ar 行中交换两者仅调用 derivedb.cpp 静态实例化,而不调用 deriveda.cpp 实例化。
我是否缺少 ar 或静态库的某些东西,这些库不知何故不能很好地与C++中的静态变量配合使用?
与直觉相反,在链接命令中包含存档与包含存档中的所有对象文件不同。仅包括归档中解析未定义符号所需的那些对象文件。如果您认为一旦没有动态链接,否则任何库(想想 C 库)的整个库都会复制到每个可执行文件中,这是一件好事。以下是 ld(1) 手册页 (GNU ld on linux) 是怎么说的:
链接器只会在命令行上指定存档的位置搜索存档一次。 如果存档在命令行上定义的某个对象中未定义的符号出现在存档之前,则链接器将包含存档中的相应文件。 但是,稍后在命令行上出现的对象中的未定义符号不会导致链接器再次搜索存档。
不幸的是,没有标准方法可以在链接的可执行文件中包含存档的每个成员。在 linux 上您可以使用 g++ -Wl,-whole-archive
,在 Mac OS X 上您可以使用 g++ -all_load
。
所以对于 GNU binutils ld,链接命令应该是
g++ -o testFactory -Wl,-whole-archive libbase.a -Wl,-no-whole-archive main.cpp
该-Wl,-no-whole-archive
可确保稍后出现在 G++ 生成的最终链接命令中的任何存档都将以正常方式链接。
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 抽象工厂结构的差异
- 下面抽象工厂设计模式的实现是正确的吗
- 工厂方法模式使用继承而抽象工厂模式使用组合如何
- 使用空基类强制继承抽象工厂的做法是不好的吗?
- 具有抽象工厂的派生类的 C++11 单例
- 抽象工厂改进
- 为工厂创建一个抽象工厂是否有意义
- 抽象工厂模式客户端代码
- C++抽象工厂是否应该为构造对象提供销毁方法
- 链接自注册的抽象工厂
- 抽象工厂的多重继承
- 在C++中实现抽象工厂 PIMPL 习语的运行时错误
- 克隆智能指针vs抽象工厂
- 抽象工厂类中的细微设计错误
- 使用抽象工厂和模板元编程的可扩展架构
- 带有参数化构造函数的抽象工厂
- 抽象工厂设计模式在c++中的应用
- 模板类困境的抽象工厂
- 这是哪种设计模式:工厂方法还是抽象工厂