C++ 虛擬函式的一個應用場景及其重要性
主要用來實現所謂的多型……我個人水平低,對於這些東西一直是沒有非常的理解。
隨著使用C++的時間變長,接觸的程式碼變多,越來越多地感覺到虛擬函式的重要作用。這裡我列舉出一個例子,供大家學習。
首先我假定讀者對於虛擬函式是有一定了解的,最起碼虛擬函式是什麼,基本作用是什麼要知道,如果不知道請參看上面的連結,或任何一本講C++的書。
開始:例子來源於qgis的C++外掛
——————————————————————————————————————————————————
一、外掛類 的基類
class QgisPlugin
在類定義中請注意 幾個純虛擬函式:
virtual void initGui() = 0;
//! Unload the plugin and cleanup the GUI
virtual void unload() = 0;
這兩個函式實現的是外掛圖形初始化以及外掛解除安裝。
QgisPlugin.h
二、 繼承自QgisPlugin的外掛類 ClientWindowclass QgisPlugin { public: QgisPlugin( QString const & name = "", QString const & description = "", QString const & category = "", QString const & version = "", PLUGINTYPE const & type = MAPLAYER ) : mName( name ), mDescription( description ), mCategory( category ), mVersion( version ), mType( type ) {} virtual ~QgisPlugin() {} //! Get the name of the plugin QString const & name() const { return mName; } QString & name() { return mName; } //! Version of the plugin QString const & version() const { return mVersion; } //! Version of the plugin QString & version() { return mVersion; } //! A brief description of the plugin QString const & description() const { return mDescription; } //! A brief description of the plugin QString & description() { return mDescription; } //! Plugin category QString const & category() const { return mCategory; } //! Plugin category QString & category() { return mCategory; } //! Plugin type, either UI or map layer QgisPlugin::PLUGINTYPE const & type() const { return mType; } //! Plugin type, either UI or map layer QgisPlugin::PLUGINTYPE & type() { return mType; } /// function to initialize connection to GUI virtual void initGui() = 0; //! Unload the plugin and cleanup the GUI virtual void unload() = 0; private: /// plug-in name QString mName; /// description QString mDescription; /// category QString mCategory; /// version QString mVersion; }; // class QgisPlugin
ClientWindow繼承了QgisPlugin
實現了 initGui(); 和 unload();
ClientWindow.h
class ClientWindow: public QObject, public QgisPlugin { Q_OBJECT public: ClientWindow( QgisInterface * theInterface ); //! Destructor virtual ~ClientWindow(); public slots: //! init the gui virtual void initGui(); //! Show the dialog box void run(); //! unload the plugin void unload(); //! show the help document void help(); private: int mPluginType; //! Pointer to the QGIS interface object QgisInterface *mQGisIface; //!pointer to the qaction for this plugin QAction * mQActionPointer; msgsprite::cMsgSprite *msg; };
ClientWindow.cpp
在這裡面實現了這2個函式。
void ClientWindow::initGui()
{
// Create the action for tool
mQActionPointer = new QAction( QIcon( ":/clientwindow/clientwindow.png" ), tr( "client window" ), this );
// Set the what's this text
mQActionPointer->setToolTip(tr( "即時通訊" ));
// Connect the action to the run
connect( mQActionPointer, SIGNAL( triggered() ), this, SLOT( run() ) );
// Add the icon to the toolbar
mQGisIface->addToolBarIcon( mQActionPointer );
mQGisIface->addPluginToMenu( tr( "&show client window" ), mQActionPointer );
}
// Unload the plugin by cleaning up the GUI
void ClientWindow::unload()
{
// remove the GUI
mQGisIface->removePluginMenu( "&show client window", mQActionPointer );
mQGisIface->removeToolBarIcon( mQActionPointer );
delete mQActionPointer;
}
三、主程式中的外掛載入過程
在主程式中,cf是生成外掛例項的函式,返回new出來的一個外掛例項指標。
通過呼叫QgisPlugin *型別的基類指標pl->initGui()來呼叫外掛中的initGui()函式。
QgisPlugin *pl = cf( mQgisInterface );
if ( pl )
{
pl->initGui();
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
不知道您看明白了沒有,再總結一下:
class QgisPlugin 是基類,其中有虛擬函式
virtual void initGui() = 0;
virtual void unload() = 0;
外掛類class ClientWindow繼承了QgisPlugin 並實現了這兩個函式
主程式通過一個QgisPlugin * 基類指標 pl->呼叫initGui(),這個時候呼叫的函式其實是ClientWindow中的initGui()函式。
這就實現了多型,也就是說外掛類可能有多種,只要是繼承了QgisPlugin 的都要實現這兩個虛擬函式,而主程式中不需要知道具體的類到底是什麼,只需要用一個類似於介面的基類QgisPlugin 指標可呼叫子類(在這裡是一個外掛)中的相關的函式。
這就是虛擬函式的功勞!除此之外不使用虛擬函式的話,你要如何實現呢?