mercredi 17 juin 2020

Manually calling constructor of base class outside initialization list

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).

Note that struct MyStruct has default values, so it cannot be initialised with named fields directly in the initialization list (e.g.: with Base({.a = a, .b = b})).

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";
        }
protected:
        Base(){} // dummy, just only 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;
}

Aucun commentaire:

Enregistrer un commentaire