C++中虚方法的误解
Virtual method misconception in C++
我没有 OOP 经验。我正在使用 C++ 和 Qt 开发应用程序。我已经实现了 2 个 classes,一个是基础的,一个是从它继承的。然后我为两者添加了虚拟方法并且一切正常。但后来我意识到我不认为它应该......这是例子:
这是我的基地 class :
namespace Ui {
class CGenericProject;
}
class CGenericProject : public QDialog
{
Q_OBJECT
public:
explicit CGenericProject(QWidget *parent = 0);
~CGenericProject();
EMeasures_t type();
private:
Ui::CGenericProject *ui;
virtual void initPlot();
protected:
QCustomPlot* customPlot;
QVector<double> m_x;
QVector<double> m_y;
EMeasures_t m_type;
};
它有一个名为 initPlot
的 virtual
方法,它看起来像这样:
void CGenericProject::initPlot()
{
customPlot = ui->workPlot;
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes );
customPlot->setFocusPolicy(Qt::ClickFocus);
customPlot->xAxis->setAutoTickStep(false);
customPlot->yAxis->setAutoTickStep(false);
customPlot->xAxis->setTickStep(100);
customPlot->yAxis->setTickStep(100);
customPlot->xAxis->setRange(0, 1000);
customPlot->yAxis->setRange(0, 1000);
}
然后我有一个 class 派生它:
class CEisProject : public CGenericProject
{
public:
CEisProject();
~CEisProject();
private:
virtual void initPlot();
void exampleEisMethod();
};
它的 initPlot
在这里:
void CEisProject::initPlot()
{
// give the axes some labels:
customPlot->xAxis->setLabel("Re [Ohm]");
customPlot->yAxis->setLabel("- Im [Ohm]");
customPlot->replot();
}
这就是我创建 object:
的方式
CGenericProject* test = new CEisProject();
现在,当调用 initPlot()
方法时,首先调用基 class CGenericProject
中的 initPlot()
,然后调用 [=23 中的 initPlot()
=] 被调用。我想要这个功能,我可以在通用 class 中预定义一些东西,然后在 child 中添加特定的东西。
不过转念一想,initPlot()
不应该是排他性的吗?我的意思是,不应该从基础 class 或 child class 调用方法,而不是 both,一个接着一个?我在阅读 this answer.
后注意到了这一点
构造函数:
CGenericProject::CGenericProject(QWidget *parent) :
QDialog(parent),
ui(new Ui::CGenericProject)
{
ui->setupUi(this);
initPlot();
m_x.clear();
m_y.clear();
}
CEisProject::CEisProject()
{
m_type = EMeasures_t::eEIS;
initPlot();
}
您没有显示构造函数的定义,只显示了它们的声明。但我很确定构造函数定义包含您问题的答案。
您可能不知道派生 class 构造函数在 将虚函数指向派生 class 之前调用基 class 构造函数 .因此,在基础 class 构造(即将派生的对象 class 中)调用的虚函数获得该虚函数的基础 class 定义。
另外,你的构造函数应该是这样的:
// File .h
CEisProject(QWidget *parent = 0);
// File .cpp
CEisProject::CEisProject(QWidget *parent) : CGenericProject(parent)
{
...
}
否则您将无法成为派生小部件的父级。
我没有 OOP 经验。我正在使用 C++ 和 Qt 开发应用程序。我已经实现了 2 个 classes,一个是基础的,一个是从它继承的。然后我为两者添加了虚拟方法并且一切正常。但后来我意识到我不认为它应该......这是例子:
这是我的基地 class :
namespace Ui {
class CGenericProject;
}
class CGenericProject : public QDialog
{
Q_OBJECT
public:
explicit CGenericProject(QWidget *parent = 0);
~CGenericProject();
EMeasures_t type();
private:
Ui::CGenericProject *ui;
virtual void initPlot();
protected:
QCustomPlot* customPlot;
QVector<double> m_x;
QVector<double> m_y;
EMeasures_t m_type;
};
它有一个名为 initPlot
的 virtual
方法,它看起来像这样:
void CGenericProject::initPlot()
{
customPlot = ui->workPlot;
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes );
customPlot->setFocusPolicy(Qt::ClickFocus);
customPlot->xAxis->setAutoTickStep(false);
customPlot->yAxis->setAutoTickStep(false);
customPlot->xAxis->setTickStep(100);
customPlot->yAxis->setTickStep(100);
customPlot->xAxis->setRange(0, 1000);
customPlot->yAxis->setRange(0, 1000);
}
然后我有一个 class 派生它:
class CEisProject : public CGenericProject
{
public:
CEisProject();
~CEisProject();
private:
virtual void initPlot();
void exampleEisMethod();
};
它的 initPlot
在这里:
void CEisProject::initPlot()
{
// give the axes some labels:
customPlot->xAxis->setLabel("Re [Ohm]");
customPlot->yAxis->setLabel("- Im [Ohm]");
customPlot->replot();
}
这就是我创建 object:
的方式CGenericProject* test = new CEisProject();
现在,当调用 initPlot()
方法时,首先调用基 class CGenericProject
中的 initPlot()
,然后调用 [=23 中的 initPlot()
=] 被调用。我想要这个功能,我可以在通用 class 中预定义一些东西,然后在 child 中添加特定的东西。
不过转念一想,initPlot()
不应该是排他性的吗?我的意思是,不应该从基础 class 或 child class 调用方法,而不是 both,一个接着一个?我在阅读 this answer.
构造函数:
CGenericProject::CGenericProject(QWidget *parent) :
QDialog(parent),
ui(new Ui::CGenericProject)
{
ui->setupUi(this);
initPlot();
m_x.clear();
m_y.clear();
}
CEisProject::CEisProject()
{
m_type = EMeasures_t::eEIS;
initPlot();
}
您没有显示构造函数的定义,只显示了它们的声明。但我很确定构造函数定义包含您问题的答案。
您可能不知道派生 class 构造函数在 将虚函数指向派生 class 之前调用基 class 构造函数 .因此,在基础 class 构造(即将派生的对象 class 中)调用的虚函数获得该虚函数的基础 class 定义。
另外,你的构造函数应该是这样的:
// File .h
CEisProject(QWidget *parent = 0);
// File .cpp
CEisProject::CEisProject(QWidget *parent) : CGenericProject(parent)
{
...
}
否则您将无法成为派生小部件的父级。