C ++-无法将派生类型作为基本类型列表传递给构造函数

时间:2019-03-05 09:27:27

标签: c++ inheritance c++14

我正在尝试实现一个类,该类是由相同抽象基类的不同数量的不同实现构造而成的。 这是一个最小的示例:

struct Base {
    virtual ~Base() {}
    virtual void something() const = 0;
}

从该基础派生出两个类(Derived1和Derived2):

class Derived1 : public Base {
public:
    void something() const override {
        std::cout << "derived 1" << std::endl;
    }
};

class Derived2 : public Base {
public:
    void something() const override {
        std::cout << "derived 2" << std::endl;
    }
};

我想做的是通过构造函数将这些类的实例传递给另一个类(集合)。我尝试使用std :: initializer_list:

实现此目的
class Collection {
public:
    Collection(std::initializer_list<Base> args) {
        for(auto& arg: args) {
            arg.something();
        }
    }
};

然后我尝试像这样调用该构造函数

Derived1 d1;
Derived2 d2;
Collection col({d1, d2});

它不编译。这是我收到的错误消息:

  

无法分配抽象类型“ Base”的对象
  因为以下虚拟函数在'Base'中是纯净的:
  'virtual void Base :: something()const'

看起来需要构造抽象基类的实例,但是为什么呢?我希望它与在初始化列表类中被调用的副本构造函数有关,但是我没有收到任何错误消息表明确实如此。 我觉得我在这里缺少了难以置信的基本知识,我似乎找不到了……

2 个答案:

答案 0 :(得分:7)

  

似乎需要构造抽象基类的实例

否,您不能创建抽象基类的实例。而是创建派生类的实例,然后使用基类引用或指向该实例的指针。

您想要做的事与

Derived1 d1; // Ok, create subclass instance
Base b = d1; // Not ok, copies only the Base part of d1, discards the rest

这称为对象切片。您可以改用

Base& b1 = d1; // Ok, reference to d1 doesn't copy/slice anything
Base *b2 = &d1; // Pointers are ok, too

根据您的情况,您可以将Collection的构造函数定义为

Collection(std::initializer_list<const Base*> args) {
    for(auto *arg: args) {
        arg->something();
    }
}

并通过

实例化它
Collection col({&d1, &d2});

答案 1 :(得分:4)

std::initializer_list<Base>是对象的集合,其最派生类型Base。这样的集合不存在,因为Base是抽象的。

您可能想要Base pointers references 的集合,例如std::initializer_list<std::reference_wrapper<Base>>