QtCreator 플러그인 개발(3) - QtCreator 구조

21178 단어
QtCreator 플러그인 개발(3) - QtCreator 구조
1. QtCreator 아키텍처 소개
QtCreator의 핵심은 플러그인 로더이며 모든 기능은 플러그인을 통해 이루어진다.QtCreator의 구조는 다음과 같다. QtCreator의 핵심 기능은 Core Plugin(Core: ICore)이 실현한다.플러그인 관리자(ExtensionSystem: Plugin Manager)는 플러그인 협업에 간단한 방식을 제공하여 플러그인이 다른 플러그인 확장에 갈고리를 제공할 수 있도록 합니다.Plugin Manager는 플러그인 로드, 관리, 제거 등의 작업을 담당합니다.코어 플러그인은 QtCreator의 가장 기초적인 플러그인으로 인터페이스에 메뉴를 추가하는 등의 기능을 제공한다.QtCreator의 핵심 시스템은 Plugin Manager 및 Core 플러그인으로 구성됩니다.Plugin Manager는 플러그인 관리를 담당하고 Core는 QtCreator의 최소 기능 집합을 제공합니다.Plugin Manager는 Core를 일반 플러그인으로 로드합니다.Core는 사용자 지정 플러그인의 경우 QtCreator의 기능을 확장할 수 있는 기본 기능 라이브러리입니다.QtCreator의 모든 기능은 플러그인으로 이루어진다. 플러그인 메커니즘을 사용하는 장점은 플러그인 관리 업무의 논리를 간소화하는 것이다. 단점은 플러그인을 불러오는 복잡도를 증가시키는 것이다. 코어 플러그인은 다른 플러그인에 의존해야 하기 때문에 qtcreator는 플러그인을 불러올 때 플러그인 간의 의존성을 고려해야 한다.
2. 플러그인 모듈
1. 플러그인 모듈
가장 기본적인 플러그인은 공유 라이브러리로 개발자의 측면에서 플러그인은 하나의 모듈이다.플러그인 모듈의 실현은 다음과 같은 기능을 만족시켜야 한다. A, 하나의 클래스에서 ExtensionSystem: IPlugin 인터페이스를 실현해야 한다.B, Q 사용EXPORT_PLUGIN 매크로는 플러그인 클래스를 내보냅니다.C. 플러그인의 메타 정보를 설명하는pluginspec 플러그인 설명 파일을 제공합니다.D. 다른 플러그 인에 하나 이상의 객체를 노출합니다.E. 다른 플러그인에 노출된 사용 가능한 하나 이상의 객체를 찾습니다.플러그인은 모두 IPlugin의 인터페이스를 계승해야 합니다. 플러그인은 설명 파일과 IPlugin을 계승하는 클래스 라이브러리로 구성됩니다.설명 파일의 내용은 다음과 같습니다.

    Scorpio.org
    (C) 2010-2011 Scorpio.org
    Do anything you want.
    A plugin that does nothing.
    http://www.scorpio.net
    
        
    

플러그인 설명 파일은 플러그인 관리자에 불러오는 데 사용할 플러그인의 기본 정보를 설명합니다.마지막 줄은 플러그인에 의존하는 다른 플러그인을 설명합니다. Plugin Manager는 플러그인 간의 의존 관계에 따라 불러오는 순서를 결정합니다.IPlugin은 플러그인의 기본 인터페이스이며 기본 인터페이스는 다음과 같습니다.
//     ,          
bool IPlugin::initialize(const QStringList &arguments, QString *errorString)
//      initialize      ,     ,                 
void IPlugin::extensionsInitialized()
//      extensionsInitialized               
bool IPlugin::delayedInitialize()

2. 노출 대상
노출 대상은 플러그인 관리자 대상 풀에 존재하는 대상입니다.플러그 인에 노출된 개체는 Plugin Manager의 개체 풀에 포함됩니다.Plugin Manager의 allobjects() 함수는 객체 풀에 있는 모든 QObject 객체의 포인터 목록을 가져오는 데 사용됩니다.다음 코드에서는 QListWidget 구성 요소에 객체 풀의 모든 객체를 나열하는 방법을 보여 줍니다.
#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 함수를 다음과 같이 수정합니다.
#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();
}

대외적으로 노출된 대상은 플러그인이 대외적으로 노출된 QObject(또는 그 하위 클래스)의 실례로 노출된 대상은 대상 탱크에 존재하며 다른 플러그인에 사용할 수 있다.
3. 플러그인에서 대상을 노출하는 방법
플러그인에서 대상을 노출하는 세 가지 방법이 있습니다: A, IPlugin::addAutoReleasedObject (QObject) B, IPlugin::addObject (QObject) C, PluginManager::addObject (QObject) IPlugin::addObject () 와 IPlugin::addAutoReleasedObject () 는 사실 모두 호출된 Plugin Manager::addObject () 함수입니다.IPlugin 함수를 사용하여 객체를 추가하는 것이 좋습니다.addAutoReleasedObject()와 addObject()의 유일한 차이점은 플러그인이 삭제될 때 자동으로 등록 순서의 반대 순서에 따라 대상 탱크에서 제거하고 delete하는 것이다.언제든지 IPlugin::removeObject(QObject) 함수를 사용하여 개체를 개체 풀에서 제거할 수 있습니다.
4、노출이 필요한 대상
플러그인은 모든 대상을 노출시킬 수 있습니다.일반적으로 다른 플러그인에 의해 일부 기능을 사용한 대상이 노출될 수 있다.QtCreator에서 기능은 인터페이스를 통해 정의됩니다.다음은 그 중 일부 인터페이스입니다: Core::INavigation Widget Factory Core::Ieditor Core::IOptions Page Core::IOutput Pane Core::::IWizard 플러그인에 인터페이스를 실현한 대상이 포함되어 있다면 이 대상은 노출되어야 합니다.예를 들어 플러그인 중의 어떤 클래스가INavigationWidgetFactory 인터페이스를 실현하고 노출되면 Core는 자동으로 이 클래스가 제공하는 구성 요소를 내비게이션 구성 요소로 표시합니다.탐색 모음 플러그인 TableNav을 만듭니다. Core::INavigationWidgetFactory 인터페이스를 통해 간단한 QTableWidget을 탐색 구성 요소로 사용합니다.Core::INavigationWidgetFactory 인터페이스는 다음과 같습니다: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 플러그인은 다음과 같습니다. 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.
    //    
    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

결과는 다음과 같습니다.
5. 노출 대상 모니터링
PluginManager::addObject()를 사용하여 객체를 추가하면 PluginManager에서 ObjectAdded(QObject) 신호를 보냅니다.응용 프로그램에서 ObjectAdded(QObject) 신호를 사용하여 추가된 객체를 확인할 수 있습니다.플러그인이 초기화되어야만 플러그인 관리자가 ObjectAdded(QObject*) 신호를 보냅니다.초기화된 후에 플러그인 관리자 대상 탱크에 추가된 플러그인 대상만 ObjectAdded () 신호를 받을 수 있습니다.일반적으로 ObjectAdded () 신호에 연결된 slot은 알려진 인터페이스를 하나 이상 찾습니다.플러그인이 INavigationWidgetFactory 인터페이스를 찾는다고 가정하면 ObjectAdded() 신호를 연결하는 슬롯 함수는 다음과 같습니다.
void xxxPlugin::slotObjectAdded(QObject * obj)
{
    INavigationWidgetFactory *factory = Aggregation::query(obj);
    if(factory)
    {
        // use it here...
    }
}

6. 객체 찾기
때때로 플러그인은 프로그램에서 일부 기능을 제공하는 대상을 찾아야 한다.현재 이미 알고 있는 대상을 찾는 방법은 두 가지가 있습니다: A, Plugin Manager::all Objects () 함수가QList 형식의 대상 풀을 되돌려줍니다.B. PluginManager:::ObjectAdded() 신호를 연결하면 노출된 대상을 알 수 있습니다.INavigationWidgetFactory 인터페이스를 실현한 대상을 찾아서 QListWidget에 추가해야 한다고 가정하십시오.그러면 PluginManager::getObjects() 함수를 사용할 수 있습니다.다음은 코드 세그먼트입니다.
ExtensionSystem::PluginManager* pm =                            ExtensionSystem::PluginManager::instance();
QList<:inavigationwidgetfactory> objects
  = pm->getObjects<:inavigationwidgetfactory>();
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);
}

3. 코어 플러그인
1. 핵심 플러그인 소개
QtCreator의 핵심 시스템은 Plugin Manager 및 Core 플러그인으로 구성됩니다.Plugin Manager는 플러그인 관리를 담당하고 코어 플러그인을 일반 플러그인으로 불러옵니다.Core 플러그인은 QtCreator의 최소 기능 집합을 제공하고 다른 플러그인에 기본 기능을 제공합니다.QtCreator의 모든 기능은 플러그인으로 이루어지는데 장점은 플러그인 관리 업무의 논리를 간소화하고 PlunginManager와 Plugin만 있다는 것이다.단점은 플러그인을 불러오는 복잡도를 증가시켰다는 것이다. 코어 베이스 라이브러리 플러그인은 다른 플러그인에 의존해야 하기 때문에 QtCreator는 플러그인을 불러올 때 플러그인 간의 의존성을 고려해야 한다.코어, Find, Locator, TextEditor의 네 가지 필수 플러그인만 포함하는 QtCreator 인터페이스는 다음과 같습니다.
2. Core 플러그인의 기능 인터페이스 집합
C++ 개발자는 일반적으로 퍼블릭 순허 함수만 포함하는 클래스를 인터페이스로 사용합니다.QtCreator에서 인터페이스는 하나 이상의 순허 함수를 가진 QObject 하위 클래스입니다.만약 플러그인이 IXX 인터페이스의 대상을 실현했다면, 이 대상은 노출되어야 한다.예를 들어 플러그인 중의 어떤 클래스가INavigationWidgetFactory 인터페이스를 실현하고 노출되면 Core는 자동으로 이 클래스가 제공하는 구성 요소를 내비게이션 구성 요소로 표시합니다.QtCreator에서 기능은 인터페이스를 통해 정의됩니다.Core 플러그인 모듈은 QtCreator의 공통 기능 인터페이스 집합을 정의합니다.Core: Core: Core: IoptionsPageCore::IWwizzard Core: IEditor Core::IeditorFactorFactory Core: IDocumumentFacgeCore::IEeditorCore Core::IcoreCore::ICoreLister Core:::IDocoreLister Core: IDocumumCore: IDocumCore Core::IDocumumCoreCoreCore:::IDocumumumCoreCoreCore:::IfififififififizzzzzzExteteteteteteteteteteteteteCore::::IIIIIIIMCoreCore:::IICore 플러그인 구현,예를 들어git 플러그인은 GitVersionControl 클래스에서 Core::IVersionControl 인터페이스를 실현했고 Core 플러그인은 TextDocument 클래스에서 IDocument 인터페이스를 실현했다.
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();

    //      initialize
    bool initialize(const QStringList &arguments, QString *errorMessage = 0);
    //      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;//     
};

} // 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   Core::IMode       , EditMode、DesignMode,  initialize         。

4. 플러그인과 핵심 시스템의 통신
1. 핵심 시스템에서 플러그인을 불러오는 방법
main 함수에서 ExtensionSystem::Plugin Manager 플러그인 관리자가 로드됩니다.pluginManager.loadPlugins();void PluginManager::loadPlugins() 함수에서 void PluginManagerPrivate::loadPlugins() 함수가 호출되었습니다.
void PluginManagerPrivate::loadPlugins()
{
    //        ,loadQueue              
    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. 플러그인은 핵심 시스템을 어떻게 사용하여 소프트웨어의 기능을 확장하는가
사용자 지정 플러그인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 함수에서 Core 플러그인을 사용하는 Core: Action Manager, Core::Action Container, Core: Command 기능으로 메인 인터페이스 메뉴 표시줄에 메뉴를 추가합니다.
Git 플러그인은 Core 플러그인에서 제공하는 기능을 사용하여 주 인터페이스 메뉴 모음의git 메뉴에 다음과 같은 메뉴와 메뉴 항목을 제공합니다.
//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);

5. 집합 실현
Aggregation 네임스페이스가 제공하는 모음은 다양한 유형의 QObject를 서로 붙여 넣을 수 있는 기능을 제공하므로 서로 다른 유형의 객체를 변환할 수 있습니다.Aggregation 네임스페이스의 클래스와 함수를 사용하면 관련 객체를 개별 솔리드(집계)로 바인딩할 수 있습니다.집합에 귀속된 대상은 집합에서 서로 다른 대상 종류로 바뀔 수 있다.
1. 집합의 전통적인 실현
객체에 대해 두 인터페이스를 구현하려면 다음 구현 코드가 필요합니다.
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;

객체 bundle은 Interface1과 Interface2를 모두 구현합니다.유형 변환 연산자를 사용하여 bundle을 Interface1 또는 Interface2로 변환할 수 있습니다.
Interface1* iface1Ptr = qobject_cast(&bundle);
Interface2* iface2Ptr = qobject_cast(&bundle);

2. QtCreator 구현 방법
QtCreator의 Aggregation 라이브러리는 인터페이스를 정의한 다음 하나의 대상으로 포장하는 더욱 간결한 방식을 제공합니다.Aggregation::Aggregate 인스턴스를 만들고 객체에 객체를 추가합니다.집합에 가입한 모든 대상은 하나의 인터페이스를 실현할 수 있다.다음 코드는 집합을 만드는 방법을 보여 줍니다.
#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);

집합 실례bundle는 현재 두 인터페이스의 실현이 있다.적절한 인터페이스로 변환해야 하는 경우 다음 코드를 사용할 수 있습니다.
Interface1* iface1Ptr = Aggregation::query(&bundle);
Interface2* iface2Ptr = Aggregation::query(&bundle);
    ,                 。  :
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을 사용하는 또 다른 장점은 delete 집합의 모든 대상이 전체 집합을 delete할 수 있다는 것이다.예를 들면 다음과 같습니다.
Aggregation::Aggregate* bundle = new Aggregation::Aggregate;
bundle->add(new Interface1);
bundle->add(new Interface2);

Interface1* iface1Ptr = Aggregation::query(bundle);
delete iface1Ptr;
//     delete    bundle        
//     delete bundle

전재 대상:https://blog.51cto.com/9291927/2105705

좋은 웹페이지 즐겨찾기