我想知道无论如何我的超类都可以为子类调用函数initValues()而不必覆盖构造函数?
以下是代码:
#ifndef VECTOR_MATH_H
#define VECTOR_MATH_H
#include "GL\glew.h"
#include <iostream>
namespace Math3d
{
class Vector
{
public:
Vector(int length=2) : v(new float[length]) { initValues(); }
~Vector() { delete[] v; }
protected:
virtual void initValues()
{
std::cout << "Vector" << std::endl;
}
float* v;
};
class Vector3 : public Vector
{
public:
protected:
void initValues()
{
std::cout << "Vector3" << std::endl;
}
};
}
#endif
然后我创建一个这样的变量: Vector3 vec;
然后我想要 initValues() 子类的方法,Vector3被调用。
这可能吗?
答案 0 :(得分:2)
如果要同时调用超类initValues()
然后调用子类initValues()
,则需要从Vector::initValues()
显式调用Vector3::initValues()
,因为动态调度将始终调用更多该方法的专门版本:
void Vector3::initValues() {
Vector::initValues();
other specific code;
}
如果你真的想按照你想要的顺序保存,那么你将需要第二种方法:
class Vector {
protected:
void initValues() {
// common init
specificInitValues();
}
virtual void specificInitValues() = 0;
};
class Vector3 : public Vector {
protected:
virtual void specificInitValues() override {
// specific init
}
};
答案 1 :(得分:2)
简要回答:不,你不能。
长答案:在调用派生类构造函数之前,对象的虚拟表不会被充实。在基类构造函数中,虚拟表指向函数的基类实现。如果基类具有实现,则将调用该函数。如果基类没有实现,则会发生与平台相关的错误/异常。
答案 2 :(得分:0)
你不能用动态多态(使用virtual
函数表,也就是作为 vtable )从构造函数中执行此操作,因为在超类尝试调用虚拟的时候方法,只构造了supeclass,并且无法从完全构造的vtable中调用子类initValues()
实现。
有两种方法可以解决这个问题:
1。让您的initValues()
方法公开,并要求在构建后从客户端调用
2。你可以做到这一点,就是改用静态多态:
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;
}
}
后一种方式,可能会查询超类中实现的抽象接口的进一步区别,以便在不了解VectorSub
且不需要的上下文中合理使用。
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;
};