C++:在共享对象中调用抽象基类构造函数/未定义的符号
C++ : calling an abstract base class constructor / undefined symbol in shared object
我正在尝试使用抽象类,在定义派生类的构造函数时遇到了一些问题。我根据这个问题的答案编写了以下代码。
#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 安装过程中,.so 是构建没有错误的,带有clang++ -shared
,但随后有一个验证步骤产生
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();
}
科利鲁的活生生的例子。
class ICommand {
private:
ICommand() = default;
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual ~ICommand() = default;
virtual void callMe() = 0;
virtual void callMe2() = 0;
};
相关文章:
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 参数包构造函数在类模板中隐藏用户定义的转换
- 具有已删除移动和复制构造函数的类的就地构造
- 创建一个没有复制构造函数的类的 std::vector 的 std::vector
- C++构造函数和类?
- 在 C++ 中,默认情况下构造函数为类的数据成员提供的值是多少?
- 如何在其他类中使用参数化构造函数制作类的对象?
- 具有值包装器的可变参数模板构造函数的类构造函数优先级
- 如何使用私有构造函数对类进行单元测试?
- C++虚拟函数:基类函数是调用的,而不是派生的
- c++17在编译时将带有已删除复制构造函数的类添加到std::vector
- 从作为模板参数传递给构造函数的类继承,或者从它们继承
- 继承的构造函数忽略类内初始化
- 模板和隐式构造函数的类定义之外的友元声明
- 具有字符串文本构造函数的类不适用于 const 引用初始化
- 为什么具有私有构造函数的类不阻止从此类继承?如何控制哪些类可以从某个基继承?
- 具有多个非默认构造函数基的Singleton派生类
- 调用基默认构造函数模板类
- 当基类未指定构造函数时,如何使用仅具有带参数的构造函数的类派生基类?
- 构造所有基类不需要默认生成的构造函数