考虑如下情形:我需要定义一个基类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
其他代码不变,运行结果: