我正在尝试实现一个类,该类是由相同抽象基类的不同数量的不同实现构造而成的。 这是一个最小的示例:
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'
看起来需要构造抽象基类的实例,但是为什么呢?我希望它与在初始化列表类中被调用的副本构造函数有关,但是我没有收到任何错误消息表明确实如此。 我觉得我在这里缺少了难以置信的基本知识,我似乎找不到了……
答案 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>>