I have a base class with a default constructor.
class Base
{
public:
Base();
private:
Type1 m_ofType1;
Type2 m_ofType2;
}
Base::Base()
: m_ofType1(defaultExpr1)
, m_ofType2(defaultExpr2)
{
}
And I have a derived class, which may be:
- default constructed, with m_ofType1 and m_ofType2 being initialized by their respective default expressions,
- provided with a Type1 only, or
- provided with a Type2 only.
class Derived : public base
{
public:
Derived(); // m_ofType1 and m_ofType2 will be initialized with their default expressions.
Derived(Type1 overrideOfType1); // m_ofType1 will be initialized with overrideOfType1 and m_ofType2 will be initialized with its default expression.
Derived(Type2 overrideOfType2); // m_ofType1 will be initialized with its default expression and m_ofType2 will be initialized with overrideOfType2.
}
Base is for Production code and Derived is for test code. I would like to implement the constructors without data or code duplication, but I can't see how.
Given the constraints, which I hope have been made clear, do you all know how to implement the above constructors without data or code duplication?
Example of code duplication:
We could add protected constructors to base:
Base(Type1);
Base(Type2);
That means that the Derived constructors would just forward the call to their respective Base constructors.
Derrived::Derrived()
: Base()
{
}
Derived::Derived(Type1 overrideOfType1)
: Base(overrideOfType1)
{
}
Derived::Derived(Type1 overrideOfType2)
: Base(overrideOfType2)
{
}
In doing this, the question changes a little. How do you implement the Base constructors without data or code duplication.
Here's my best attempt at doing this. It doesn't work, and I'll show you why.
First, add another constructor to Base:
Base(Type1 ofType1, Type2 ofType2);
Base::Base() : Base(defaultExpr1, defaultExpr2) { }
Base::Base(Type1 overrideOfType1) : Base(overrideOfType1, defaultExpr2) { }
Base::Base(Type2 overrideOfType2) : Base(defaultExpr1, overrideOfType2) { }
Base::Base(Type1 ofType1, Type1 ofType2) : m_ofType1(ofType1) , m_ofType2(ofType2) { }
You can see that defaultExpr1 and defaultExpr2 have been duplicated.
You can pass the arguments to private members 1 & 2 with a protected constructor. This will keep those members shielded without giving the derived classes full access to them.
Oh, and by the way, members are initialized with the default constructor if they have one automatically, so you don't need to be explicit for the empty base constructor. For instance, if the default constructor of
Basewas accessible, you could just define:And the members would have their default values.