Łukasz Przeniosło
Łukasz Przeniosło

Reputation: 2949

Virtual method misconception in C++

I am not experienced in OOP. I am developing an application using C++ and Qt. I have implemented 2 classes, base one and the one that inherits from it. Then I have added virtual methods for both and everything worked. But then I realized that I don't think it should... Here is the example:

This is my base 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;
};

It has a virtual method called initPlot and it looks like this:

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

And then i have a class that derives it:

class CEisProject : public CGenericProject
{
public:
    CEisProject();
    ~CEisProject();

private:
    virtual void initPlot();
    void exampleEisMethod();
};

its initPlot is here:

void CEisProject::initPlot()
{
    // give the axes some labels:
    customPlot->xAxis->setLabel("Re [Ohm]");
    customPlot->yAxis->setLabel("- Im [Ohm]");

    customPlot->replot();
}

This is how i create the object:

CGenericProject* test = new CEisProject();

Now, when the initPlot() method is called, first the initPlot() from base class CGenericProject is called and then initPlot() from CEisProject is called. I wanted this functionality, where I can predefine some stuff in generic class and then add specific stuff in the childs. But when I think of it, shouldn't initPlot() be calles exclusevily? I mean, shouldn't the method be called from base class or child class, instead of both, one after another? I have noticed this after reading this answer.

Constructors:

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

Upvotes: 0

Views: 174

Answers (2)

Miki
Miki

Reputation: 41775

Also, your constructor should be like:

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

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

or you won't be able to parent your derived widgets.

Upvotes: 2

JSF
JSF

Reputation: 5321

You did not show the definition of the constructors, just their declaration. But I'm pretty sure the constructor definitions contain the answer to your question.

You may not be aware that the derived class constructor calls the base class constructor before directing virtual functions to the derived class. So a virtual function called in the base class construction (of an object which will soon be derived class) gets the base class definition of that virtual function.

Upvotes: 2

Related Questions