c – 抽象类为std :: initializer_list对象
发布时间:2020-12-16 09:56:37 所属栏目:百科 来源:网络整理
导读:为了获得更清晰的语法,我想使用std :: initializer_list将对象列表发送到构造函数.然而,这些对象是抽象的,这会导致一个问题:在VS 2013中,它丢失了vfptr引用,给出了“R6025:纯虚函数调用”运行时错误,而且它抱怨它“无法分配一个抽象对象”在编译期间输入“
为了获得更清晰的语法,我想使用std :: initializer_list将对象列表发送到构造函数.然而,这些对象是抽象的,这会导致一个问题:在VS 2013中,它丢失了vfptr引用,给出了“R6025:纯虚函数调用”运行时错误,而且它抱怨它“无法分配一个抽象对象”在编译期间输入“base”.我猜测编译器试图复制对象(这是不可取的 – 它们可能很大),但仅成功复制基类,因此错误.我的问题是:是否有一个解决方案:(1)避免复制对象和(2)不是大量冗长,否定“更清晰的语法”优势?下面的代码说明了我的问题:
#include <cstdio> #include <initializer_list> struct base{ virtual void foo() const = 0; }; struct derived : public base{ int i; derived(int i) : i(i) {} void foo() const{ printf("bar %i",i); } }; void foo_everything(const std::initializer_list<base> &list){ for (auto i = list.begin(),iend = list.end(); i != iend; i++) i->foo(); } int main(void){ // Works fine derived d(0); base * base_ptr = &d; base_ptr->foo(); // Does not work fine foo_everything({ derived(1),derived(2),derived(3) }); } 请注意,使用base&在模板错误中,因为std :: initializer_list尝试“[形成一个]指向引用类型base&”的指针,并且在使用base *时,然后获取每个派生类的地址确实在实际工作,它通过采取临时的地址,因此不安全(g抱怨).如果我在方法调用之外声明派生类(我的临时解决方案),后者确实有效,但它仍然比我希望的更冗长. 解决方法
使用initializer_list< base *>的一些hackish方法:
template<class... Ts> void foo_everything(Ts&&... args){ std::initializer_list<base *> list = {&args...}; for(auto i : list) i->foo(); } 然后从通话中删除大括号: foo_everything(derived(1),derived(3)); 如果你真的不需要转换为base *并执行虚拟调用,并且只想在传入的每个对象上调用foo(),那么我们可以使用通常的pack-expansion-inside-an-initializer-list技巧: template<class... Ts> void foo_everything(Ts&&... args){ using expander = int[]; (void) expander { 0,((void) std::forward<Ts>(args).foo(),0)...}; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |