新聞中心
QtCreator插件開發(fā)(三)——QtCreator架構(gòu)
一、QtCreator架構(gòu)簡(jiǎn)介
QtCreator的核心就是一個(gè)插件加載器,其所有功能都是通過插件實(shí)現(xiàn)的。
QtCreator架構(gòu)如下:
QtCreator的核心功能由Core Plugin (Core::ICore)實(shí)現(xiàn)。
插件管理器(ExtensionSystem::PluginManager)對(duì)插件協(xié)作提供了簡(jiǎn)單方式,允許插件為其他插件擴(kuò)展提供鉤子。
PluginManager負(fù)責(zé)插件的加載,管理,銷毀等工作。Core插件是QtCreator最基礎(chǔ)的插件,提供了向界面增加菜單等功能。
QtCreator的核心系統(tǒng)是由PluginManager和Core插件構(gòu)成。PluginManager負(fù)責(zé)插件的管理工作,Core負(fù)責(zé)提供QtCreator的最小功能集合。PluginManager將Core當(dāng)做普通插件進(jìn)行加載。對(duì)于自定義插件,Core是一個(gè)基礎(chǔ)功能庫,使用Core可以擴(kuò)展QtCreator的功能。
QtCreator的所有功能,全是由插件實(shí)現(xiàn)的,使用插件機(jī)制的優(yōu)點(diǎn)是簡(jiǎn)化了頂層業(yè)務(wù),即插件管理工作的邏輯,缺點(diǎn)是增加了加載插件的復(fù)雜度,由于Core插件需要被其他插件依賴,所以qtcreator在插件加載時(shí)就必須要考慮插件之間的依賴性。
創(chuàng)新互聯(lián)是工信部頒發(fā)資質(zhì)IDC服務(wù)器商,為用戶提供優(yōu)質(zhì)的雙線服務(wù)器托管服務(wù)
二、插件模塊
1、插件模塊
最基本的插件是一個(gè)共享庫,從開發(fā)者的角度,插件是一個(gè)模塊。
插件模塊的實(shí)現(xiàn)需要滿足以下功能:
A、在一個(gè)類中實(shí)現(xiàn)ExtensionSystem::IPlugin接口。
B、使用Q_EXPORT_PLUGIN宏導(dǎo)出插件類。
C、提供一個(gè)pluginspec插件描述文件,用于描述插件的元信息。
D、向其它插件暴露一個(gè)或多個(gè)對(duì)象。
E、查找其它插件暴露出來的可用的一個(gè)或多個(gè)對(duì)象。
插件都需要繼承IPlugin的接口,插件是由描述文件和繼承IPlugin的類庫組成。
描述文件內(nèi)容如下:
Scorpio.org
(C) 2010-2011 Scorpio.org
Do anything you want.
A plugin that does nothing.
http://www.scorpio.net
插件描述文件描述了插件的基本信息,用于被插件管理器加載。最后一行描述了插件所依賴的其它插件,PluginManager會(huì)根據(jù)插件之間的依賴關(guān)系決定加載順序。
IPlugin是插件的基類接口,主要接口如下:
//初始化函數(shù),在插件被加載時(shí)會(huì)調(diào)用
bool IPlugin::initialize(const QStringList &arguments, QString *errorString)
//在所有插件的initialize函數(shù)被調(diào)用后,調(diào)用該函數(shù),此時(shí)該插件依賴的插件已經(jīng)初始化完成
void IPlugin::extensionsInitialized()
//在所有插件的extensionsInitialized函數(shù)調(diào)用完成以后進(jìn)行調(diào)用
bool IPlugin::delayedInitialize()
2、暴露對(duì)象
暴露對(duì)象是存在于插件管理器對(duì)象池中的對(duì)象。
插件暴露出的對(duì)象會(huì)加入到PluginManager的對(duì)象池。PluginManager的allObjects()函數(shù)用于獲取對(duì)象池中所有QObject對(duì)象的指針列表。下面的代碼演示了如何在QListWidget組件中列出對(duì)象池中所有的對(duì)象:
#include
ExtensionSystem::PluginManager* pm
= ExtensionSystem::PluginManager::instance();
QList objects = pm->allObjects();
QListWidget* listWidget = new QListWidget;
Q_FOREACH(QObject* obj, objects)
{
QString objInfo = QString("%1 (%2)")
.arg(obj->objectName())
.arg(obj->metaObject()->className());
listWidget->addItem(objInfo);
}
將DoNothing插件中doNothing函數(shù)修改如下:
#include
void DoNothingPlugin::doNothing()
{
ExtensionSystem::PluginManager* pm
= ExtensionSystem::PluginManager::instance();
QList objects = pm->allObjects();
QListWidget* listWidget = new QListWidget();
Q_FOREACH(QObject* obj, objects)
{
QString objInfo = QString(QString::fromUtf8("%1 (%2)"))
.arg(obj->objectName())
.arg(QString::fromUtf8(obj->metaObject()->className()));
listWidget->addItem(objInfo);
}
listWidget->resize(300,600);
listWidget->show();
}
一個(gè)對(duì)外暴露的對(duì)象是由一個(gè)插件對(duì)外暴露的QObject(或其子類)的實(shí)例,暴露對(duì)象存在于對(duì)象池中,并且可供其它插件使用。
3、如何從插件中暴露對(duì)象
有三種方法從插件中暴露一個(gè)對(duì)象:
A、IPlugin::addAutoReleasedObject(QObject)
B、IPlugin::addObject(QObject)
C、PluginManager::addObject(QObject)
IPlugin::addObject()和IPlugin::addAutoReleasedObject()其實(shí)都是調(diào)用的PluginManager::addObject()函數(shù)。建議使用IPlugin的函數(shù)添加對(duì)象。addAutoReleasedObject()和addObject()的唯一區(qū)別是,前者添加的對(duì)象會(huì)在插件銷毀的時(shí)候自動(dòng)按照注冊(cè)順序的反向順序從對(duì)象池中移除并delete。
在任意時(shí)刻,都可以使用IPlugin::removeObject(QObject)函數(shù)將對(duì)象從對(duì)象池中移除。
4、需要暴露的對(duì)象
插件可以暴露任何對(duì)象。通常,被其它插件使用了某些功能的對(duì)象會(huì)被暴露。QtCreator中,功能通過接口的方式定義。
下面是其中一些接口:
Core::INavigationWidgetFactory
Core::IEditor
Core::IOptionsPage
Core::IOutputPane
Core::IWizard
如果一個(gè)插件包含實(shí)現(xiàn)了接口的對(duì)象,那么這個(gè)對(duì)象就應(yīng)該被暴露出來。例如,一個(gè)插件中的某個(gè)類實(shí)現(xiàn)了INavigationWidgetFactory接口,并且暴露出來,那么Core就會(huì)自動(dòng)把這個(gè)類提供的組件當(dāng)做導(dǎo)航組件顯示出來。創(chuàng)建一個(gè)導(dǎo)航欄插件TableNav,通過實(shí)現(xiàn)?Core::INavigationWidgetFactory接口,將一個(gè)簡(jiǎn)單的QTableWidget當(dāng)做導(dǎo)航組件。
Core::INavigationWidgetFactory接口實(shí)現(xiàn)如下:
NavWidgetFactory.h文件:
#ifndef NAVWIDGETFACTORY_H
#define NAVWIDGETFACTORY_H
#include
#include
using namespace Core;
class NavWidgetFactory : public Core::INavigationWidgetFactory
{
public:
NavWidgetFactory();
~NavWidgetFactory();
Core::NavigationView createWidget();
QString displayName() const;
int priority() const;
Id id() const;
};
#endif // NAVWIDGETFACTORY_H
NavWidgetFactory.cpp文件:
#include "NavWidgetFactory.h"
#include
NavWidgetFactory::NavWidgetFactory() { }
NavWidgetFactory::~NavWidgetFactory() { }
Core::NavigationView NavWidgetFactory::createWidget()
{
Core::NavigationView view;
view.widget = new QTableWidget(50, 3);
return view;
}
QString NavWidgetFactory::displayName() const
{
return QString::fromUtf8("TableNav");
}
int NavWidgetFactory::priority() const
{
return 0;
}
Id NavWidgetFactory::id() const
{
return Id::fromName("TableNav");
}
TableNav插件實(shí)現(xiàn)如下:
TableNavPlugin .h文件:
#ifndef TABLENAVPLUGIN_H
#define TABLENAVPLUGIN_H
#include
#include "NavWidgetFactory.h"
#include
#include
class TableNavPlugin : public ExtensionSystem::IPlugin
{
public:
TableNavPlugin();
~TableNavPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // TABLENAVPLUGIN_H
TableNavPlugin .cpp文件:
#include "TableNavPlugin.h"
#include "NavWidgetFactory.h"
#include
#include
TableNavPlugin::TableNavPlugin()
{
// Do nothing
}
TableNavPlugin::~TableNavPlugin()
{
// Do notning
}
bool TableNavPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Provide a navigation widget factory.
// Qt Creator’s navigation widget will automatically
// hook to our INavigationWidgetFactory implementation, which
// is the NavWidgetFactory class, and show the QTableWidget
// created by it in the navigation panel.
//暴露對(duì)象
addAutoReleasedObject(new NavWidgetFactory);
return true;
}
void TableNavPlugin::extensionsInitialized()
{
// Do nothing
}
void TableNavPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(TableNavPlugin)
TableNav插件描述文件如下:
Scorpio
(C) 2010-2011 Scorpio.org
MIT
Table widget as navigation.
http://www.scorpio.net
TableNav插件依賴文件如下:
QTC_PLUGIN_NAME = TableNav
QTC_PLUGIN_DEPENDS += \
coreplugin
TableNav插件工程文件如下:
EMPLATE = lib
TARGET = TableNav
include(../../qtcreatorplugin.pri)
PROVIDER = Scorpio
include(../../plugins/coreplugin/coreplugin.pri)
HEADERS += TableNavPlugin.h \
NavWidgetFactory.h
SOURCES += TableNavPlugin.cpp \
NavWidgetFactory.cpp
OTHER_FILES += TableNav.pluginspec \
TableNav_dependencies.pri
結(jié)果如下:
5、監(jiān)控暴露對(duì)象
當(dāng)使用PluginManager::addObject()添加對(duì)象時(shí),PluginManager就會(huì)發(fā)出objectAdded(QObject)信號(hào)。應(yīng)用程序可以使用objectAdded(QObject)信號(hào)來弄清楚被添加的對(duì)象。
只有插件被初始化后,插件管理器才會(huì)發(fā)出objectAdded(QObject*)信號(hào)。只有被初始化后添加到插件管理器對(duì)象池的插件對(duì)象,才能收到objectAdded()信號(hào)。
通常,連接到objectAdded()信號(hào)的slot會(huì)尋找一個(gè)或多個(gè)已知接口。假設(shè)插件要找的是INavigationWidgetFactory接口,那么連接objectAdded()信號(hào)的槽函數(shù)如下:
void xxxPlugin::slotObjectAdded(QObject * obj)
{
INavigationWidgetFactory *factory = Aggregation::query(obj);
if(factory)
{
// use it here...
}
}
6、查找對(duì)象
有時(shí),插件需要在應(yīng)用程序中查找提供了某些功能的對(duì)象。目前,已知查找對(duì)象的方法有兩種:
A、PluginManager::allObjects()函數(shù)返回一個(gè)QList
B、通過連接PluginManager::objectAdded()信號(hào),可以知道被暴露的對(duì)象。
假設(shè)需要查找一個(gè)實(shí)現(xiàn)了INavigationWidgetFactory接口的對(duì)象,然后把它添加到一個(gè)QListWidget中顯示出來。那么,可以使用PluginManager::getObjects
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
QList objects
= pm->getObjects();
QListWidget* listWidget = new QListWidget();
Q_FOREACH(Core::INavigationWidgetFactory* obj, objects)
{
QString objInfo = QString("%1 (%2)")
.arg(obj->displayName())
.arg(obj->metaObject()->className());
listWidget->addItem(objInfo);
}
三、Core插件
1、Core插件簡(jiǎn)介
QtCreator的核心系統(tǒng)由PluginManager和Core插件構(gòu)成。PluginManager負(fù)責(zé)插件的管理工作,將Core插件當(dāng)做普通插件進(jìn)行加載;Core插件負(fù)責(zé)提供QtCreator的最小功能集合,為其它插件提供基礎(chǔ)功能。
QtCreator所有功能由插件實(shí)現(xiàn),優(yōu)點(diǎn)是簡(jiǎn)化了頂層業(yè)務(wù),即插件管理工作的邏輯,只有PlunginManager和Plugin;缺點(diǎn)是增加了加載插件的復(fù)雜度,因?yàn)镃ore基礎(chǔ)庫插件需要被其他插件依賴,所以QtCreator在插件加載時(shí)就必須要考慮插件之間的依賴性。
只包括core、Find、Locator、TextEditor四個(gè)必須插件的QtCreator界面如下:
2、Core插件的功能接口集合
C++?開發(fā)者通常會(huì)將只包含?public純虛函數(shù)的類當(dāng)做接口。在QtCreator中,接口則是擁有一個(gè)或多個(gè)純虛函數(shù)的QObject子類。如果一個(gè)插件實(shí)現(xiàn)了IXXX接口的對(duì)象,那么這個(gè)對(duì)象就應(yīng)該被暴露出來。例如,一個(gè)插件中的某個(gè)類實(shí)現(xiàn)了INavigationWidgetFactory接口,并且暴露出來,那么 Core 就會(huì)自動(dòng)把這個(gè)類提供的組件當(dāng)做導(dǎo)航組件顯示出來。
QtCreator中,功能通過接口的方式定義。Core插件模塊定義了QtCreator的常用功能接口集合,如下:
Core::IOptionsPage
Core::IWizard
Core::IEditor
Core::IEditorFactory
Core::IDocumentFactory
Core::IExternalEditor
Core::IContext
Core::ICore
Core::ICoreListener
Core::IDocument
Core::IFileWizardExtension
Core::IMode
Core::INavigationWidgetFactory
Core::IOutputPane
Core::IVersionControl
功能接口會(huì)在其它插件或Core插件實(shí)現(xiàn),如git插件在GitVersionControl類對(duì)Core::IVersionControl接口進(jìn)行了實(shí)現(xiàn),Core插件在TextDocument類中對(duì)IDocument接口進(jìn)行了實(shí)現(xiàn)。
3、Core插件的源碼
coreplugin.h文件:
#ifndef COREPLUGIN_H
#define COREPLUGIN_H
#include
namespace Core {
class DesignMode;
namespace Internal {
class EditMode;
class MainWindow;
class CorePlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Core.json")
public:
CorePlugin();
~CorePlugin();
//必須實(shí)現(xiàn)接口initialize
bool initialize(const QStringList &arguments, QString *errorMessage = 0);
//必須實(shí)現(xiàn)接口extensionsInitialized
void extensionsInitialized();
bool delayedInitialize();
ShutdownFlag aboutToShutdown();
QObject *remoteCommand(const QStringList & /* options */, const QStringList &args);
public slots:
void fileOpenRequest(const QString&);
private:
void parseArguments(const QStringList & arguments);
MainWindow *m_mainWindow;//主窗口
EditMode *m_editMode;//編輯模式
DesignMode *m_designMode;//設(shè)計(jì)器模式
};
} // namespace Internal
} // namespace Core
#endif // COREPLUGIN_H
coreplugin.cpp文件:
#include "coreplugin.h"
#include "actionmanager.h"
#include "designmode.h"
#include "editmode.h"
#include "editormanager.h"
#include "fileiconprovider.h"
#include "helpmanager.h"
#include "mainwindow.h"
#include "mimedatabase.h"
#include "modemanager.h"
#include "infobar.h"
#include
#include
#include
#include
using namespace Core;
using namespace Core::Internal;
CorePlugin::CorePlugin() :
m_mainWindow(new MainWindow), m_editMode(0), m_designMode(0)
{
}
CorePlugin::~CorePlugin()
{
if (m_editMode) {
removeObject(m_editMode);
delete m_editMode;
}
if (m_designMode) {
if (m_designMode->designModeIsRequired())
removeObject(m_designMode);
delete m_designMode;
}
// delete FileIconProvider singleton
delete FileIconProvider::instance();
delete m_mainWindow;
}
void CorePlugin::parseArguments(const QStringList &arguments)
{
for (int i = 0; i < arguments.size(); ++i) {
if (arguments.at(i) == QLatin1String("-color")) {
const QString colorcode(arguments.at(i + 1));
m_mainWindow->setOverrideColor(QColor(colorcode));
i++; // skip the argument
}
if (arguments.at(i) == QLatin1String("-presentationMode"))
ActionManager::setPresentationModeEnabled(true);
}
}
bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
qsrand(QDateTime::currentDateTime().toTime_t());
parseArguments(arguments);
const bool success = m_mainWindow->init(errorMessage);
if (success) {
m_editMode = new EditMode;
addObject(m_editMode);
//切換到編輯模式
ModeManager::activateMode(m_editMode->id());
m_designMode = new DesignMode;
InfoBar::initializeGloballySuppressed();
}
// Make sure we respect the process's umask when creating new files
Utils::SaveFile::initializeUmask();
return success;
}
void CorePlugin::extensionsInitialized()
{
m_mainWindow->mimeDatabase()->syncUserModifiedMimeTypes();
if (m_designMode->designModeIsRequired())
addObject(m_designMode);
m_mainWindow->extensionsInitialized();
}
bool CorePlugin::delayedInitialize()
{
HelpManager::instance()->setupHelpManager();
return true;
}
QObject *CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args)
{
IDocument *res = m_mainWindow->openFiles(
args, ICore::OpenFilesFlags(ICore::SwitchMode | ICore::CanContainLineNumbers));
m_mainWindow->raiseWindow();
return res;
}
void CorePlugin::fileOpenRequest(const QString &f)
{
remoteCommand(QStringList(), QStringList(f));
}
ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown()
{
m_mainWindow->aboutToShutdown();
return SynchronousShutdown;
}
Q_EXPORT_PLUGIN(CorePlugin)
Core插件對(duì)Core::IMode進(jìn)行了不同實(shí)現(xiàn),如EditMode、DesignMode,并在initialize函數(shù)加載了相應(yīng)功能。
四、插件與核心系統(tǒng)的通信
1、核心系統(tǒng)如何加載插件
在main函數(shù)中由ExtensionSystem::PluginManager插件管理器加載。
pluginManager.loadPlugins();
void PluginManager::loadPlugins()函數(shù)調(diào)用了void PluginManagerPrivate::loadPlugins()函數(shù)。
void PluginManagerPrivate::loadPlugins()
{
//獲取待加載的插件,loadQueue根據(jù)插件批次依賴關(guān)系進(jìn)行排序
QList queue = loadQueue();
//加載插件
foreach (PluginSpec *spec, queue) {
loadPlugin(spec, PluginSpec::Loaded);
}
//初始化插件
foreach (PluginSpec *spec, queue) {
loadPlugin(spec, PluginSpec::Initialized);
}
QListIterator it(queue);
it.toBack();
while (it.hasPrevious()) {
loadPlugin(it.previous(), PluginSpec::Running);
}
emit q->pluginsChanged();
}
2、插件如何使用核心系統(tǒng)為軟件擴(kuò)展功能
自定義插件使用Core插件提供的功能向界面添加菜單代碼如下:
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle(QString::fromUtf8("DoNothing"));
// Create a command for "About DoNothing".
Core::Command* cmd = am->registerAction(
new QAction(this),
"DoNothingPlugin.AboutDoNothing",
Core::Context(Core::Constants::C_GLOBAL));
cmd->action()->setText(QString::fromUtf8("About DoNothing"));
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(doNothing()));
// Insert the "DoNothing" menu between "Window" and "Help".
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QMenuBar* menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(helpMenu->menuAction(), ac->menu());
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
return true;
}
DoNothing插件在initialize函數(shù)中使用Core插件的Core::ActionManager、Core::ActionContainer、Core::Command功能向主界面菜單欄添加菜單。
Git插件使用Core插件提供的功能向主界面菜單欄的git菜單提供菜單和菜單項(xiàng),代碼如下:
//register actions
Core::ActionContainer *toolsContainer =
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
Core::ActionContainer *gitContainer = Core::ActionManager::createMenu("Git");
gitContainer->menu()->setTitle(tr("&Git"));
toolsContainer->addMenu(gitContainer);
m_menuAction = gitContainer->menu()->menuAction();
/* "Current File" menu */
Core::ActionContainer *currentFileMenu = Core::ActionManager::createMenu(Core::Id("Git.CurrentFileMenu"));
currentFileMenu->menu()->setTitle(tr("Current &File"));
gitContainer->addMenu(currentFileMenu);
五、聚合實(shí)現(xiàn)
聚合由Aggregation命名空間提供,提供了一種將不同類型的QObject粘合在一起的能力,因此可以將不同類型對(duì)象相互轉(zhuǎn)換。使用Aggregation命名空間中的類和函數(shù),就可以綁定相關(guān)對(duì)象到一個(gè)單獨(dú)實(shí)體(聚合)。被綁定到聚合中的對(duì)象能夠從聚合轉(zhuǎn)換為不同的對(duì)象類類型。
1、聚合的傳統(tǒng)實(shí)現(xiàn)
如果想要一個(gè)對(duì)象提供兩個(gè)接口的實(shí)現(xiàn),實(shí)現(xiàn)代碼如下:
class Interface1
{
....
};
Q_DECLARE_INTERFACE("Interface1", "Interface1");
class Interface2
{
....
};
Q_DECLARE_INTERFACE("Interface2", "Interface2");
class Bundle : public QObject,
public Interface1,
public Interface2
{
Q_OBJECT
Q_INTERFACES(Interface1 Interface2)
....
};
Bundle bundle;
對(duì)象bundle同時(shí)實(shí)現(xiàn)了Interface1和Interface2??梢允褂妙愋娃D(zhuǎn)換運(yùn)算符,將bundle轉(zhuǎn)換成Interface1或者Interface2:
Interface1* iface1Ptr = qobject_cast(&bundle);
Interface2* iface2Ptr = qobject_cast(&bundle);
2、QtCreator實(shí)現(xiàn)方式
QtCreator的Aggregation庫提供了一種更加簡(jiǎn)潔的方式,來定義接口,然后將其打包成一個(gè)對(duì)象。創(chuàng)建Aggregation::Aggregate實(shí)例,然后將對(duì)象添加進(jìn)該對(duì)象。加入聚合的每一個(gè)對(duì)象都可以實(shí)現(xiàn)一個(gè)接口。下面的代碼顯示了如何創(chuàng)建聚合。
#include
class Interface1 : public QObject
{
Q_OBJECT
public:
Interface1() { }
~Interface1() { }
};
class Interface2 : public QObject
{
Q_OBJECT
public:
Interface2() { }
~Interface2() { }
};
Aggregation::Aggregate bundle;
bundle.add(new Interface1);
bundle.add(new Interface2);
聚合實(shí)例bundle現(xiàn)在有兩個(gè)接口的實(shí)現(xiàn)。如果需要轉(zhuǎn)換成相應(yīng)接口,可以使用如下代碼:
Interface1* iface1Ptr = Aggregation::query(&bundle);
Interface2* iface2Ptr = Aggregation::query(&bundle);
利用聚合,可以多次添加具有相同接口的多個(gè)對(duì)象。例如:
Aggregation::Aggregate bundle;
bundle.add(new Interface1);
bundle.add(new Interface2);
bundle.add(new Interface1);
bundle.add(new Interface1);
QListgt; iface1Ptrs = Aggregation::query_all(&bundle);
使用Aggregation的另一優(yōu)點(diǎn)是,delete聚合中的任一對(duì)象,都可以將整個(gè)聚合delete掉。例如:
Aggregation::Aggregate* bundle = new Aggregation::Aggregate;
bundle->add(new Interface1);
bundle->add(new Interface2);
Interface1* iface1Ptr = Aggregation::query(bundle);
delete iface1Ptr;
// 同時(shí)會(huì) delete 這個(gè) bundle 及其中所有對(duì)象
// 等價(jià)于 delete bundle
網(wǎng)站欄目:QtCreator插件開發(fā)(三)——QtCreator架構(gòu)
轉(zhuǎn)載注明:http://fisionsoft.com.cn/article/gpccjg.html