C++ : calling an abstract base class constructor/undefined symbol in shared object

标签 c++ inheritance shared-libraries abstract-class r-package

我正在尝试使用抽象类,但在定义派生类的构造函数时遇到了一些问题。我根据这个question的答案编写了以下代码.

#include <string>
#include <iostream>

class ICommand {
private:
  ICommand();
public:
  const std::string name;
  ICommand(const std::string& name) : name(name) { }
  virtual void callMe(); 
  virtual void callMe2();
};


class MyCommand : public ICommand {
public:
  int x;
  MyCommand(const std::string& name) : ICommand(name) { }
  MyCommand(const std::string& name, int x) : ICommand(name), x(x) { }
  void callMe() { 
    std::cout << name << "\n"; 
  }
  void callMe2() { 
    std::cout << name << x << "\n"; 
  }
};

void f(std::string name) {
  MyCommand A(name);
  A.callMe();
}

编译没有错误。然而我的目标是为 R 包构建一个 .so)。在 R 安装过程中,使用 clang++ -shared 构建 .so 时没有错误,但随后有一个验证步骤,会生成

unable to load shared object '/path/object.so':
/path/object.so: undefined symbol: _ZTI8ICommand

我以前遇到过此类问题,并且有解决方法 - 不调用 Icommand(name) 相当简单,但我想了解那里发生了什么,并且如果可能的话,如何避免解决方法。

预先感谢您的想法。

回答

为了方便以后的读者:这里唯一需要的改变是将抽象类中虚函数的定义替换为

  virtual void callMe() = 0; 
  virtual void callMe2() = 0;

这使得它们成为纯虚函数。为什么这能解决问题完全让我困惑。

最佳答案

与:

class MyClass {
private:
    MyClass();
};

您正在删除默认构造函数。如果您想调用默认构造函数,则(声明或)定义或不定义一个默认构造函数,但不要删除它。您的派生类默认构造函数将调用基类默认构造函数:

#include <string>
#include <iostream>
#include <memory>

class ICommand {
public:
    std::string name;
    ICommand() : name("The name") { std::cout << "Default base class constructor." << std::endl; }
    virtual void callMe() = 0;
};

class MyCommand : public ICommand {
public:
    MyCommand(){ std::cout << "Default derived class constructor." << std::endl; };
    void callMe() override {
        std::cout << name << std::endl;
    }
};

void f2(const std::string& name) {
    std::shared_ptr<ICommand> p = std::make_shared<MyCommand>();
    p->callMe();
}
int main(){
    f2("asdasd");
}

第 2 部分:
如果您尝试以多态方式使用上述类,请使您的 ICommand 成员函数纯虚拟:

virtual void callMe() = 0; 
virtual void callMe2() = 0;

void f 函数修改为:

void f(const std::string& name) {
    std::shared_ptr<ICommand> p = std::make_shared<MyCommand>(name);
    p->callMe();
}

Live example在 Coliru 上。

关于C++ : calling an abstract base class constructor/undefined symbol in shared object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45264480/

相关文章:

c++ - 如何创建一个QJsonDocument?

c# - 同时调用基本构造函数和无参数构造函数?

java - 泛型和继承

c - 两个共享库实现相同的 API

c++ - 调用@plt函数时dlopen/static init上的共享库SIGSEGV

c++ - 捕获音频输出

c++ - 如何创建库?

java - 使用类型继承的数字组层次结构

c++ - 隐藏包含父库

c++ - Visual C++ 不会创建 dll 文件并在 *.lib 处停止