正在尝试使用虚拟部件手动创建unique_ptr类实例

Trying to manually creating unique_ptr class instances with virtual parts

本文关键字:unique 创建 ptr 实例 虚拟部      更新时间:2023-10-16

作为一篇硕士论文,我需要在github上用功能扩展数据库duckdb。

第一步是创建一个固定的内部计划,只在物理层面上代表"选择42"。为此,我厌倦了用duckdb内部使用的类手动创建这样一个计划。

在编译时,我通常会收到这样的错误消息:

/home/ubuntu/git/duckdb/src/include/common/helper.hpp: In instantiation of ‘std::unique_ptr<T> duckdb::make_unique(Args&& ...)
[with T = duckdb::Expression; Args = {duckdb::ExpressionType,
duckdb::ExpressionClass, duckdb::TypeId}]’:   
/home/ubuntu/git/duckdb/src/execution/physical_plan_generator.cpp:125:155:
required from here   
/home/ubuntu/git/duckdb/src/include/common/helper.hpp:24:23: error:
invalid new-expression of abstract class type ‘duckdb::Expression’   
return unique_ptr<T>(new T(std::forward<Args>(args)...));

创建是这样的行:

unique_ptr<Expression> ProjectionExpression = make_unique<Expression>(ExpressionType::VALUE_CONSTANT, ExpressionClass::BOUND_CONSTANT, TypeId::INTEGER);

构造函数是

Expression::Expression(ExpressionType type, ExpressionClass expression_class, TypeId return_type)
: BaseExpression(type, expression_class), return_type(return_type) {
}

基础表达为

BaseExpression(ExpressionType type, ExpressionClass expression_class)
: type(type), expression_class(expression_class) {
}
virtual ~BaseExpression() {
}

正如您所看到的,类表达式使用了class baseExpression中的初始化列表。据我所知,2之间没有直接继承,但很明显,我需要一些目前缺失的东西来正确初始化构造函数。

问题是,通常在duckdb中,这些东西来自解析器,然后由这些对象构建。我必须试着猜测数据结构应该是什么样子。

我在弄清楚如何用make_unique直接分配这个对象时遇到了问题,因为表达式显然需要某种类型的baseExpression,但baseExpression本身有一个虚拟组件,所以我也不能直接创建那个。

基本上我要问的是:当类是抽象的时,如何创建一个新的unique_ptr对象?

当类是抽象的时,如何创建新的unique_ptr对象?

通过创建一个具体的非抽象子类的实例,并将其作为指向抽象基类的指针返回。这是使用Factory模式和类似习惯用法时的常见做法。

查看此处的源代码,您会发现Expression有一个纯虚拟成员函数(可由virtual= 0识别(:

class Expression : public BaseExpression {
//...
virtual unique_ptr<Expression> Copy() = 0;
//...
};

具有纯虚拟成员函数的类是抽象类。无法创建抽象类的实例(无论是作为具有自动存储持续时间的变量、使用new还是使用std::make_unique(。相反,您需要选择从实现所有纯虚拟方法的Expression派生的适当类,并创建该类的实例,例如通过调用std::make_unique<DerivedClass>(...)。之后,您仍然可以将其分配给std::unique_ptr<Expression>

问题不在于一般的虚拟成员函数,而在于纯虚拟成员函数。如果没有纯虚拟成员函数,则具有虚拟函数的类可以毫无问题地与std::make_unique一起使用。