类的继承以及虚函数

考虑如下情形:我需要定义一个基类CTemplate给同事使用,而且这个基类被封装为dll库。同事可以选择在他的项目里直接使用我的类。但是这个类有一个函数,名为iOperation(int x, int y),作用是计算两个输入变量,x,y的和。同事可能会对成员函数iOperation()的功能不满意,想重新定义iOperation(int x, int y)的功能,变成求乘积x*y。于是他可以选择从这个基类派生出新的类来使用。新类也有iOperation()函数,但是是由同事重写的。派生类中其他的public成员,protected成员都与基类一致。

根据以上情况,我给出基类CTemplate以及派生类CInherit的代码。

#ifndef CTEMPLATE_H
#define CTEMPLATE_H

#include <QObject>

class CTemplate : public QObject
{
    Q_OBJECT
public:
    explicit CTemplate(QObject *parent = 0);
    /*virtual*/ int         iOperation(int, int);
    int                 iUseOperation(int, int, int);
signals:

public slots:
};

#endif // CTEMPLATE_H


#include "ctemplate.h"

CTemplate::CTemplate(QObject *parent) : QObject(parent)
{

}

int CTemplate::iOperation(int x, int y)
{
    return x + y;
}

int CTemplate::iUseOperation(int x, int y, int z)
{
    return iOperation(x,y)%z;
}
#ifndef CINHERIT_H
#define CINHERIT_H

#include "ctemplate.h"

class CInherit : public CTemplate
{
    Q_OBJECT
public:
    explicit CInherit(QObject *parent = 0);
    int     iOperation(int, int);
signals:

public slots:
};

#endif // CINHERIT_H


#include "cinherit.h"

CInherit::CInherit(QObject *parent) : CTemplate(parent)
{

}

int CInherit::iOperation(int x, int y)
{
    return x * y;
}

假如在如下的窗体里调用CTemplate  CInherit并对两者结果做对比,你会发现,CInherit::iOperation的行为确实变了,但是CInherit::iUseOperation的行为没有像预想那样变化:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "cinherit.h"


template <typename T>
void vNewClass(T * & p)
{
    p = new T;
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->Btn_iOperation, SIGNAL(clicked()), this, SLOT(OnStartOperation()));
    connect(ui->Btn_iUseOperation, SIGNAL(clicked()), this, SLOT(OnStartUseOperation()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::OnStartOperation(void)
{
    CInherit * pInherit = NULL;
    CTemplate * pTemp = NULL;
    vNewClass(pInherit);
    vNewClass(pTemp);

    ui->Edt_iOperation2->setText(QString("%1").arg(pInherit->iOperation(2, 10)));
    ui->Edt_iOperation->setText(QString("%1").arg(pTemp->iOperation(2, 10)));
}

void MainWindow::OnStartUseOperation(void)
{
    CInherit * pInherit = NULL;
    CTemplate * pTemp = NULL;
    vNewClass(pInherit);
    vNewClass(pTemp);

    ui->Edt_iUseOperation2->setText(QString("%1").arg(pInherit->iUseOperation(2, 10, 3)));
    ui->Edt_iUseOperation->setText(QString("%1").arg(pTemp->iUseOperation(2, 10, 3)));
}

运行结果:

这是因为,CInherit仅仅重写了iOperation函数,并没有重写iUseOperation函数。因此,CInherit::iUseOperation 还是在调用 CTemplate::iOperation。解决这个问题的办法是,将CTemplate::iOperation定义为虚函数:

#ifndef CTEMPLATE_H
#define CTEMPLATE_H

#include <QObject>

class CTemplate : public QObject
{
    Q_OBJECT
public:
    explicit CTemplate(QObject *parent = 0);
    virtual int         iOperation(int, int);
    int                 iUseOperation(int, int, int);
signals:

public slots:
};

#endif // CTEMPLATE_H

其他代码不变,运行结果:

发布了148 篇原创文章 · 获赞 46 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/liji_digital/article/details/89343995