我有一个基类和两个派生类。基类构造函数应在调用时计算某些属性,尽管这些属性取决于派生类的详细信息。为了避免在每个派生类构造函数中重新编码相同的步骤,我在基类构造函数中编写这些步骤,如下例所示。
问题在于,当我这样做时,基类构造函数不会调用重写的方法。相反,它调用自己的方法。有办法解决这个问题吗?虽然它也有意义,但是这种行为发生的原因是什么?
来自C#背景,这很奇怪,因为它可以在那里很好地工作。在C#中,我将使用关键字base
来调用任何基类方法,而this
总是调用派生类方法。
示例:
example.h文件
#define _USE_MATH_DEFINES
#include <math.h>
class Base
{
public:
Base(void);
~Base(void);
protected:
virtual void Method(void);
};
class Derived : public Base
{
public:
Derived(void);
~Derived(void);
protected:
virtual void Method(void);
};
#include <iostream>
Base::Base()
{
this->Method(); // This calls Base->Method instead of Derived->Method
}
Base::~Base(){}
void Base::Method() // If I remove this, I have an error "externals undefined"
{
std::cout << "called Base->Method()" << endl;
}
Derived::Derived()
: Base()
{
this->Method(); // This obviously calls Derived->Method
}
Derived::~Derived(){}
void Derived::Method()
{
std::cout << "called Derived->Method()" << endl;
}
int main()
{
Base* d = new Derived();
/*
Outputs:
called Base->Method()
called Derived->Method()
*/
}
答案 0 :(得分:1)
没有办法做到这一点,因为在运行基类构造函数时,该对象还不是派生类型的对象。特别是,派生类中引入的数据成员直到运行基类构造函数之后才会初始化 - 实质上,基类对象的行为类似于派生类的数据成员。
无论如何,您必须推迟计算,直到输入派生类的构造函数为止。如果我理解您正在尝试正确执行的操作,最好的方法可能是为基类提供一个成员函数来执行计算并从派生类中调用它。构造
答案 1 :(得分:1)
构造函数和析构函数是virtual
功能无法启动的唯一地方
因为尚未构造Derived
对象,并且调用Derived
函数会导致未定义的行为。在析构函数的情况下,Derived
对象已被破坏。
Bjarne Stroustrup's Technical FAQ page中解释了这一点。
剩下的唯一方法是让对象构建,然后调用Method()
。