C++ C+中的虚拟方法误解+;

C++ C+中的虚拟方法误解+;,c++,qt,inheritance,virtual,C++,Qt,Inheritance,Virtual,我没有OOP方面的经验。我正在开发一个应用程序使用C++和Qt。我已经实现了两个类,一个是基类,另一个是继承类。然后我为这两种方法都添加了虚拟方法,一切都正常。但后来我意识到我不认为它应该。。。以下是一个例子: 这是我的基类: namespace Ui { class CGenericProject; } class CGenericProject : public QDialog { Q_OBJECT public: explicit CGenericProject(QWi

我没有OOP方面的经验。我正在开发一个应用程序使用C++和Qt。我已经实现了两个类,一个是基类,另一个是继承类。然后我为这两种方法都添加了虚拟方法,一切都正常。但后来我意识到我不认为它应该。。。以下是一个例子:

这是我的基类:

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;
};
然后我有一个派生它的类:

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();
}
以下是我创建对象的方式:

CGenericProject* test = new CEisProject();
现在,当调用
initPlot()
方法时,首先调用基类
CGenericProject
中的
initPlot()
,然后调用
CEisProject
中的
initPlot()
。我想要这个功能,我可以在泛型类中预定义一些东西,然后在childs中添加特定的东西。 但是当我想到它时,
initPlot()
不应该被唯一调用吗?我的意思是,该方法不应该从基类或子类调用,而应该一个接一个地从两者调用吗?我在阅读后注意到了这一点

建造商:

    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();
}

您没有显示构造函数的定义,只显示了它们的声明。但是我很确定构造函数的定义包含了你问题的答案


您可能不知道派生类构造函数在将虚拟函数定向到派生类之前调用基类构造函数。因此,在基类构造中调用的虚拟函数(即将派生为类的对象)将获得该虚拟函数的基类定义。

您没有显示构造函数的定义,只是显示它们的声明。但是我很确定构造函数的定义包含了你问题的答案


您可能不知道派生类构造函数在将虚拟函数定向到派生类之前调用基类构造函数。因此,在基类构造(即将派生为类的对象)中调用的虚拟函数将获得该虚拟函数的基类定义。

此外,您的构造函数应该如下所示:

// File .h
CEisProject(QWidget *parent = 0);

// File .cpp
CEisProject::CEisProject(QWidget *parent) : CGenericProject(parent)
{
    ...
}

或者,您将无法为派生小部件设置父级。

此外,您的构造函数应该类似于:

// File .h
CEisProject(QWidget *parent = 0);

// File .cpp
CEisProject::CEisProject(QWidget *parent) : CGenericProject(parent)
{
    ...
}

或者您将无法为派生小部件设置父级。

只应调用覆盖函数(此处,
CEisProject::initPlot
)。如果在你的代码中都调用了这两个函数,那么你的代码中有一些东西你没有向我们展示。我会给你关于这一点的所有信息。我逐步地发现,在<代码> CEISTPATS/<代码>创建<代码> IITPrime >从代码> CGNICICPARTION/CODEC>首先被归类。“我不是要用目标语言来实现。”——NITSCOD: C++不是面向对象语言。面向对象编程只是C++提供的工具之一,近年来,它已经成为了一种新的编程方式,它对LAMBDAS和函数式编程有很大的吸引力和重要性。你可以同时做这两件事。不要忘记C++ C++ lambda是创建整个类的语法糖,然后实例化它。如果这不是OOP,我不知道是什么。@KubaOber:虽然你可以同时做这两件事,但他们通常也在竞争。如果你看看C++11附带的所有东西,几乎没有一项创新涉及OOP概念(我只能想到
final
override
)。OOP是指在运行时选择函数的实现,即使用虚拟函数。lambda有些不同。您可以使用lambdas构建自己的“虚拟功能”机制。lambda创建的匿名类没有虚拟函数。只应调用重写函数(此处,
CEisProject::initPlot
)。如果在你的代码中都调用了这两个函数,那么你的代码中有一些东西你没有向我们展示。我会给你关于这一点的所有信息。我逐步地发现,在<代码> CEISTPATS/<代码>创建<代码> IITPrime >从代码> CGNICICPARTION/CODEC>首先被归类。“我不是要用目标语言来实现。”——NITSCOD: C++不是面向对象语言。面向对象编程只是C++提供的工具之一,近年来,它已经成为了一种新的编程方式,它对LAMBDAS和函数式编程有很大的吸引力和重要性。你可以同时做这两件事。不要忘记C++ C++ lambda是创建整个类的语法糖,然后实例化它。如果这不是OOP,我不知道是什么。@KubaOber:虽然你可以同时做这两件事,但他们通常也在竞争。如果你看看C++11附带的所有东西,几乎没有一项创新涉及OOP概念(我只能想到
final
override
)。OOP是指在运行时选择函数的实现,即使用虚拟函数。lambda有些不同。您可以使用lambdas构建自己的“虚拟功能”机制。由lambda创建的匿名类没有虚拟函数。我添加了构造函数。这意味着当我调用派生类时,基类构造函数也会被调用?现在这很有意义:P.当你构造派生类时,它总是先构造基类。如上所述,基类构造函数和派生类构造函数都调用initPlot()。两个构造函数都被执行,并且每个构造函数都调用自己的initPlot。您应该理解,调用这两个函数的行为并不是来自initPlot是虚拟的(您最初的问题),而是来自任何派生类构造函数中对基类构造函数的隐含调用。然而,这可能意味着您的代码中存在问题。有这样一个init函数的通常原因是,有时您需要重新初始化