今天在写项目的时候,需要使用到多态的效果,因此就设计了三个类,一个基类,一个派生类,外加一个派生类中需要使用到的界面类。
大体结构如下:
///< 基类 >
// 头文件
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_wgttest.h"
class QTabWidget;
class WgtTest : public QMainWindow
{
Q_OBJECT
public:
WgtTest(QWidget *parent = Q_NULLPTR);
protected:
virtual void initWgt();
virtual void initTagWgt(){} // 不执行任何操作
protected:
Ui::WgtTestClass ui;
QTabWidget* m_tabWgt;
};
// 源文件
#include <QTabWidget>
#include <QGridLayout>
#include <QHBoxLayout>
#include "wgttest.h"
WgtTest::WgtTest(QWidget *parent)
: QMainWindow(parent)
, m_tabWgt(new QTabWidget(this))
{
ui.setupUi(this);
initWgt();
}
void WgtTest::initWgt()
{
QHBoxLayout* pLayout = new QHBoxLayout;
pLayout->addWidget(m_tabWgt);
ui.widget->setLayout(pLayout);
initTagWgt();
}
//< 派生类 >
// 头文件
#pragma once
#include "wgttest.h"
class FrmChildWgt1 : public WgtTest
{
Q_OBJECT
public:
FrmChildWgt1(QWidget *parent = nullptr);
~FrmChildWgt1();
protected:
virtual void initTagWgt() override;
};
// 源文件
#include "frmchildwgt1.h"
#include "frmwgt1.h"
FrmChildWgt1::FrmChildWgt1(QWidget *parent)
: WgtTest(parent)
{
}
FrmChildWgt1::~FrmChildWgt1()
{
}
void FrmChildWgt1::initTagWgt()
{
FrmWgt1* wgt = new FrmWgt1(m_tabWgt);
m_tabWgt->addTab(wgt, "test_tab1");
}
还有一个类是培生累中用到的界面类,直接上图吧:
然后在main.cpp文件中如下书写:
#include "wgttest.h"
#include <QtWidgets/QApplication>
#include "frmchildwgt1.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 使用方式1(派生类对象)
FrmChildWgt1 w;
w.show();
// 使用方式2(派生类指针)
//FrmChildWgt1* pWgt = new FrmChildWgt1;
//pWgt->show();
// 使用方法3(基类指针指向派生类对象)
//WgtTest* pWgt = new FrmChildWgt1;
//pWgt->show();
return a.exec();
}
其中使用了三种方式,结果发现界面始终都是基类的界面,如下所始终没有出现派生类的界面。
后查阅资料后发现,原因出在 —— 构造函数中无法实现多态。
至于其原因,可很好理解,在构造一个对象的时候,首先会调用其基类的构造函数,执行基类构造函数中的代码,而此时,其派生类还没有被构造,这就导致即便派生类中重写了某个虚函数,但是还是无法被调用的情况。
子类构造时,先会调用父类构造函数,父类构造函数中调用initTabWg(),虽然它是一个虚函数,但是此时子类还处于构造过程中并没有构建完成,因此无法调用派生类的实现,只能调用父类本身的实现,我们看到的就是无法呈现多态了。
鉴于此,将上述代码中的initWgt()函数暴露出来,作为接口,随后取消在构造函数中的调用,紧接着在构造完基类之后,执行initWgt()函数即可实现多态效果,如下:
public:
virtual void initWgt();
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
WgtTest* pWgt = new FrmChildWgt1;
pWgt->initWgt();
pWgt->show();
return a.exec();
}
此时就可正确调用派生类中的函数了,界面如下: