tmlen
tmlen

Reputation: 9090

Executing code before calling base class constructor

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

class Derived : public Base {
private:
    static std::pair<int, int> determine_a_and_b_(int k);
public:
    explicit Derived(int k);
};

Derived::Derived(int k) :
    // a, b from determine_a_and_b_(k)...
    Base(a, b) { }

Is there any way to call determine_a_and_b_ in the constructor of Derived, to get the values a and b, before calling Base::Base?

It seems that the only way would be to refactor Base so that it can first be default-constructed into a null object, and then be initialized with a and b later, like

Derived::Derived(int k) : Base() {
    Base::init_(a, b);
}

Is there any better way to do this, without needing to change Base?

Edit - made determine_a_and_b_ static

Upvotes: 4

Views: 1598

Answers (2)

NathanOliver
NathanOliver

Reputation: 180630

What you can do here is write a function that returns a Base and in the function create the base from the std::pair returned by determine_a_and_b_. This allows you to conditionally initialize base in the member initialization list. You would have something like

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

class Derived : public Base {
private:
    static std::pair<int, int> determine_a_and_b_(int k);
    static Base create_base(const std::pair<int, int>& params) { return Base(params.first, params.second); }
public:
    explicit Derived(int k);
};

Derived::Derived(int k) : Base(create_base(determine_a_and_b_(k)) {}

Upvotes: 4

Jeffrey
Jeffrey

Reputation: 11410

Calling member functions before your constructor even starts running is always shady. You end up running code on an object that is not yet constructed.

One alternative is to derive from a second base. That base class is inited first, picks a and b, and you then use those to init your second base class:

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

class Params
{
protected:
    Params()
    {
    // this replaces std::pair<int, int> determine_a_and_b_(int k);
    // put your logic here
        _values.first = 0;
        _values.second = 1;
    }
    std::pair<int, int> _values;
};

class Derived : public Params, public Base {
private:
public:
    explicit Derived(int k);
};

Derived::Derived(int k) :
    Base(_values.first, _values.second) 
{

}

Upvotes: 3

Related Questions