Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional call to base constructor

Currently, I have a based class with two different constructors:

class Base {
public:
   Base(std::string filname){...}
   Base(int a, int b) {...}
};

and a derived class of Base class. What I would like to do is to choose which constructor call inside the constructor of the derived class, but not in the initializer list. Something like this:

class Derived : public Base {
public:
    Derived() {
        if( /* exists("myFile") */ )
            this->Base("myFile");
        else
            this->Base(1,2);
    }
}

Is it possible to do that?, or because the base class is initialize before the derived class, the only way to call to the base constructor is in the initializer list?

Thanks

like image 339
marolafm Avatar asked Jun 12 '18 14:06

marolafm


2 Answers

The choice of which base constructor is called happens before the body of the function and there's no way to change it at run time like that. However, you might be able to get close. If the base class also has a move constructor, or you could you add one, you could use that:

class Derived : public Base {
public:
    Derived()
        : Base{ exists("myFile") ? Base{"myFile"} : Base{1, 2} } {
    }
}

This will call exists("myFile"); if that returns true, it will construct a temporary Base using the first constructor, and if it returns false it will construct a temporary Base using the second constructor. Either way, it will then construct the actual base subobject using this temporary.

like image 74
Daniel H Avatar answered Sep 30 '22 10:09

Daniel H


You can simulate that by introducing a factory function:

class Base {
public:
    Base(std::string filname);
    Base(int a, int b);
};

class Derived : public Base {
    Derived(std::string filname) : Base(filname) {}
    Derived(int a, int b) : Base(a, b) {}
public:
    static Derived create() {
        if( /* exists("myFile") */ )
            return Derived("myFile");
        else
            return Derived(1,2);
    }
};

int main(){
    auto d = Derived::create();
}

Alternatively, if derivation from Base is not required, an instance of Base can be held as a member (std::unique_ptr or std::aligned_storage) that you can initialise however you please.

like image 25
Maxim Egorushkin Avatar answered Sep 30 '22 08:09

Maxim Egorushkin