在初始化列表之外手动调用基类的构造函数 [英] Manually calling constructor of base class outside initialization list

查看:82
本文介绍了在初始化列表之外手动调用基类的构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Derived 类,其构造函数必须填充作为参数传递的 struct 的字段到 Base 类的构造函数。我希望能够命名要填充的结构的字段,以使我的代码适应未来(例如:抵抗 MyStruct )。

I have a Derived class whose constructor has to populate the fields of a struct that is passed as an argument to the constructor of the Base class. I want to be able to name the fields of the struct that I am populating, to keep my code future-proof (i.e.: resistant to addition and/or reordering of the members of MyStruct).

请注意, struct MyStruct 具有默认值,因此无法直接在其中使用命名字段进行初始化初始化列表(例如: Base({。a = a,.b = b})不起作用)。另外,就我而言, Base 的副本构造函数也被删除。另外,我正在使用C ++ 11。

Note that struct MyStruct has default values, so it cannot be initialised with named fields directly in the initialization list (e.g.: Base({.a = a, .b = b}) does not work). Also, in my case, Base's copy constructor is deleted. Also, I am using C++ 11.

我想到的解决方案使用 placement new 运算符手动调用 Base 类的构造函数在 this 指向的内存上。为此,我还必须在 Base 类中添加受保护的默认构造函数。这种方法是否有任何弊端和/或有人可以建议一种更好的方法?

The solution I came up with uses the placement new operator to manually call the constructor of the Base class on the memory pointed to by this. To achieve this I also had to add a protected default constructor to my Base class. Are there any possible downsides to this approach and/or could anyone suggest a better method?

#include <iostream>

struct MyStruct
{
        int a = 0;
        int b = 1;
};

class Base
{
public:
        Base(MyStruct str){
                std::cout << "a: " << str.a << ", b: " << str.b << "\n";
        }
        Base(Base&&) = delete; // no copy constructor
protected:
        Base(){ // dummy, does exactly nothing.
                // it only exists to be called by
                // the derived class's constructor
        }
private:
        int amember;
};

class Derived : public Base
{
public:
        Derived(int a, int b)
        {
                MyStruct str;
                str.a = a;
                str.b = b;
                new (this) Base(str);
        }
private:
        int anothermember;
};

int main()
{
        MyStruct str;
        str.a = 10;
        str.b = 20;
        Base b(str);
        Derived d(10, 20);
        return 0;
}

编辑:添加提及不能复制Base,明确指出 Base :: Base()完全不执行任何操作。

edit: added mention that Base cannot be copied, made explicit that Base::Base() does exactly nothing.

推荐答案

使用辅助函数代替例如

class Derived : public Base
{
public:
        Derived(int a, int b) : Base(make_mystruct(a, b)), anothermember(some_value) {}
private:
        int anothermember;
        static MyStruct make_mystruct(int a, int b) { return MyStruct(a, b); }
};

这篇关于在初始化列表之外手动调用基类的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆