You can't do this with dynamic polymorphism (using a virtual
function table, aka. as vtable) from the constructor, because at the point the superclass tries to call the virtual method, only the supeclass is constructed yet, and the subclass initValues()
implementation can't be called from the fully constructed vtable.
There are two ways to overcome this issue:
1. Make your initValues()
method public, and require it to be called from clients after construction
2. You could do to achieve this behavior, is to use static polymorphism instead:
template<class Derived>
class VectorSuper
{
public:
VectorSuper(int length=2)
: v(new float[length])
{
static_cast<Derived*>(this)->initValues();
}
~VectorSuper() { delete[] v; }
protected:
void initValues() // Note, no virtual
{
std::cout << "VectorSuper" << std::endl;
}
float* v;
};
class VectorSub
: public VectorSuper<VectorSub>
{
protected:
void initValues() // Note, no virtual
{
VectorSuper<VectorSub>::initValues();
std::cout << "VectorSub" << std::endl;
}
}
The latter way, might inquire some further distinction of an abstract interface implemented in the superclass, to be reasonably usable in a context that doesn't know about VectorSub
, and doesn't need to.
class AbstractVector
{
public:
virtual ~AbstractVector() = 0;
// example interface
virtual float operator[](int index) const = 0;
};
template<class Derived>
class VectorSuper
: public AbstractVector
{
public:
VectorSuper(int length_=2)
: length(length_), v(new float[length])
{
static_cast<Derived*>(this)->initValues();
}
~VectorSuper() { delete[] v; }
virtual float operator[](int index) const
{
if(index >= length || index < 0)
{
throw std::invalid_argument("index");
}
return v[index];
}
protected:
// ... as before
int length; // Remember length additionally!
float* v;
};