【问题标题】:Program which behavior changes depending on classes it is linked against程序的行为会根据它所链接的类而改变
【发布时间】:2015-04-25 08:29:33
【问题描述】:

我认为我尝试的东西不够花哨,值得“插件”这个词,但我正在尝试做的事情:

给定文件 a.h、a.cpp 和 main.cpp,我想创建其他文件,例如:

g++ -o test main.cpp a.cpp b.cpp

导致测试程序做某事,并且

g++ -o test main.cpp a.cpp c.cpp

做别的事。

这部分我已经开始工作了,参见下面的代码。 我的问题是:有没有可能

 g++ -o test main.cpp a.cpp

做一些默认行为?我尝试了几件事,但我总是得到一些未定义的东西。

到目前为止我的代码:

// a.h    

#ifndef A_H_
#define A_H_

class A {
 public:
  A();
  ~A();
  virtual void print()=0;
};

#endif


// a.cpp

#include <iostream>
#include "a.h"

A::A(){}
A::~A(){}


// b.h

#include "a.h"

class B: public A {
 public:
  B();
  ~B();
  void print();
};


// b.cpp

#include <iostream>
#include "b.h"

B::B(){}
B::~B(){}
void B::print(){
  std::cout << "I am B" << std::endl;
}

A* a = new B();


//  code in c.h and c.cpp similar to the one in b.h and b.cpp
//   just "B" replaced by "C"

// main.cpp

#include "a.h"

extern A* a;

int main(){
  a->print();
}

针对 b.cpp 编译时,代码打印“I am B”,针对 c.cpp 编译时,代码打印“I am C”。

我想要:

g++ -o test main.cpp a.cpp

让测试要么什么都不做,要么做一个默认行为。不需要很简单。

【问题讨论】:

    标签: c++ plugins linker extern


    【解决方案1】:

    这是一个使用弱符号的(非便携式)选项。

    啊.h

    struct A {
      public:
        virtual void print() = 0;
    };
    
    struct Dummy: A {
      void print() override {};
    };
    
    A* init();
    

    main.cpp

    #include "a.h"
    
    A* __attribute__((weak)) init()
    {
      return new Dummy;
    }
    
    int main()
    {
      A* a = init();
      a->print();
    }
    

    b.cpp

    #include "a.h"
    #include <iostream>
    
    struct B: A
    {
      void print() override {
        std::cout << "B" << std::endl;
      }
    };
    
    A* init()
    {
      return new B;
    }
    

    如果您不与b.cpp 或任何其他提供init 函数的实体链接,则将使用main.cpp 中的那个。如果你链接b.cpp,就会使用那个人的定义。

    这种为init 函数提供了一个“默认实现”,并允许您通过不使用全局变量来管理初始化(这里并不重要,但是一旦您充实了您的插件系统就会变得更加棘手)。

    【讨论】:

    • 看起来很棒!没有任何全局变量是一个很大的优势。 “非便携式”是什么意思?我应该注意的任何限制?
    • C(或 C++)标准没有说明这种事情,所以没有使用这种技术的可移植解决方案(可能有使用其他技术的可移植解决方案,我只是没有虽然知道一个)。语法是 GCC 语法,clang 可能支持它,也许还有其他一些。不适用于例如MSVC,但其他编译器/链接器可能具有类似的功能。
    • 似乎对我有用,但我会在接受之前稍等片刻,以防万一有人提出更便携的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2014-10-19
    • 1970-01-01
    • 2021-05-04
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多