代码之家  ›  专栏  ›  技术社区  ›  Hind Forsum

为什么c++静态对象没有链接到共享库或静态库[重复]

  •  1
  • Hind Forsum  · 技术社区  · 6 年前

    如果标题没有完全解释清楚,我很抱歉。我试图理解为什么我的单例工厂模式不能正常工作,并且我在使用库和链接单对象文件时遇到了一个奇怪的差异。

    下面是代码的简化版本:

    主.cpp

    #include <iostream>
    #include "bar.hpp"
    
    int main (int /*argc*/, char** /*argv*/)
    {
      A::get().print();
      return 0;
    }
    

    钢筋水电站

    #ifndef BAR_HPP
    #define BAR_HPP
    
    #include <iostream>
    
    class A
    {
    public:
      static A& get ()
      {
        static A a;
        return a;
      }
      bool set(const int i)
      {
        m_i = i;
        print();
        return true;
      }
      void print ()
      {
        std::cout << "print: " << m_i << "\n";
      }
    private:
    
      int m_i;
      A () : m_i(0) {}
    };
    #endif // BAR_HPP
    

    巴兹水电站

    #ifndef BAZ_HPP
    #define BAZ_HPP
    
    #include "bar.hpp"
    
    namespace
    {
    static bool check = A::get().set(2);
    }
    
    #endif // BAZ_HPP
    

    #include "baz.hpp"
    

    现在,我用两种方式构建我的“项目”:

    生成文件:

    all:
      g++ -std=c++11 -c baz.cpp
      g++ -std=c++11 -o test main.cpp baz.o
    lib:
      g++ -std=c++11 -c baz.cpp
      ar rvs mylib.a baz.o
      g++ -std=c++11 -o test main.cpp mylib.a
    

    以下是我得到的结果:

    $ make all
    $ ./test
    print: 2
    print: 2
    
    $ make lib
    $ ./test
    print: 0
    

    在第一种情况下 A::get().set(2) 在baz.hpp中发生,然后在主函数中使用相同的A实例化,因此打印 2 . 在第二种情况下 A: :get().set(2个) 0 )是印刷品。

    编辑:正如Richard所解释的,原因是main.cpp中不需要baz.cpp中定义的符号,因此baz.o不会从库中提取并链接。这就提出了另一个问题:是否有一种解决方法来确保指令 A: :get().set(2个) 被处决了?我不想让singleton成为全局对象,但我不确定它是否可能。我也希望避免将baz.hpp包含在主目录中,因为可能有许多 bazxyz.hpp

    0 回复  |  直到 8 年前
        1
  •  1
  •   Richard Hodges    8 年前

    如果这是一个静态库,那么某处的某个模块就必须在要在工厂注册的对象的每个实现文件中处理一些内容。

    bar.cpp (这是一个你还没有的文件)。它将包含 A

    只有当对象文件链接到可执行文件中时,自我发现才起作用。这使c++启动序列有机会了解并构造具有全局链接的所有对象。