So recently i have been working on a basic math library in c++ and decided to make template classes and inherited, specialised classes, for example Vector.
I have had some problems with linking default constructor of parent class without having the need to make a new one. I can see that the using keyword also allows me to use any of the base class constructors that I want, but the other solution (the one below) seems more elegant.
template<typename type>
class Vector3D : public Vector<type, 3>
{
public:
/// Telling compiler to use constructors of parent class Vector
using Vector<type, 3>::Vector;
Vector3D() : KMath::Vector<type, 3>() {}
As I see that both of these approaches work, I'm curious what are the differences between those and if any of these is better/more widely used?
Edit: For explicity I will paste the parent class here:
template<typename type, unsigned int SIZE>
class Vector
{
protected:
type vectorTuple[SIZE];
public:
explicit Vector()
{
unsigned int i;
for (i = 0; i < SIZE; ++i)
{
vectorTuple[i] = 0.0;
}
}
explicit Vector(type arr[SIZE])
{
unsigned int i;
for (i = 0; i < SIZE; ++i)
{
vectorTuple[i] = arr[i];
}
}
...
};
My problem was not only with the default constructor being called, but also with the other one, as without the using keyword compiler would return an error if I attemted
double arr[3] = {1, 2, 3};
Vector3D<double> vec(arr);
Without the using keyword or creating the same kind of constructor in the derived class, the code would obviously not work. I have seen this solution somewhere on the web and was just curious to see if it has any implications.
TL;DR - in your snippet, you do not need either. Your constructors are default constructors, do not use arguments and you could easily remove using
declaration, as well as a explicit default constructor.
In more general case, using
declaration for base constructor makes it visible in the child class (otherwise it is hidden by the implicit child's class default constructor).
When you employ it, base class constructors become available in the child class, and allow one to construct child class by calling one of the base's constructors with matching signature.
For example:
struct Base {
Base(int );
};
struct Derived : Base {
// using Base::Base;
};
void foo() {
Derived d{1}; // Fails unless using directive is uncommented above
}
This approach is viable when derived classes do not need to perform any initialization of their own, and simply want to make available base construction.
Please note, using
base's constructor doesn't block derived classes from creating their own. For example:
struct Base {
Base(int );
};
struct Derived : Base {
using Base::Base;
Derived(const char* str);
};
In the example above, Dervived d{1}
will call Base:Base(int )
, while Derived d{"hello"}
will call Derived::Derived(const char*)
On the other hand, explicitly calling base constructors from derived constructors is usable when there is some logic associated with derived class constructor - i.e. non-default member initialization without default initializers, non-trivial body, etc. For example:
struct Base {
Base(int );
};
struct Derived : Base {
Derived(int x) : Base(x), own(x + 5) { }
int own;
};
In this case, Derived
constructor needs to do two things - call Base
with int
argument and initialize own
. So using
Base's constructor would not be appropriate, as it would leave own
uninitialized.