2012-02-09 14 views
2

Qtはスロット内のテンプレートを許可しないため、以下の解決策を成功させようとしました。プラグインメカニズムを使用してランタイム中にデータ型を動的にロードする方法

まず、このようなリストを作成したいと思います:

list commands = 
0, "MyDashboard", DashBoard0 
1, "MomsDashboard", Dashboard1 

ダッシュボード0と1が両方のウィジェット

から派生しているあなたは私たちがリストに文字列を追加し、QListWidgetを考えてみましょう

connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), 
     this, SLOT(addDashboard(QListWidgetItem*))); 

void addDashboard(QListWidgetItem* item) { 
    int index = listWidget->row(item); 

    QWidget* widget = new typeof(command.atIndex(index).getType()); 
    widget->show(); 

} 

C#タイプと同じように、リストとストアの種類を作成するにはどうすればよいですか?

+2

Emileの答えであなたのコメントを読んだら、明示的に質問を編集する必要があります - コンパイル時に知られているタイプか、プラグインメカニズムを通して動的にロードされているタイプですか? – cmannett85

答えて

3

C++では、(new演算子を使用して)型を実行時にしか認識できないオブジェクトを作成することはできません。ただし、簡略化された形式のFactory Methodパターンを回避策として使用できます。ここで

は例です:私が知っている、

// Type IDs that are associated with a widget type 
enum WidgetTypeId { 
    dashboard1WidgetTypeId, 
    dashboard2WidgetTypeId 
}; 

// Factory method 
QWidget* createWidget(WidgetTypeId type) { 
    switch (type) 
    { 
     case dashboard1WidgetTypeId: 
      return new DashBoard0; 

     case dashboard2WidgetTypeId: 
      return new DashBoard1; 
    } 
} 

void addDashboard(QListWidgetItem* item) { 
    int index = listWidget->row(item); 

    QWidget* widget = createWidget(command.atIndex(index).getWidgetTypeId()); 
    widget->show(); 

} 

非常にきれいではありません。ウィジェットがクローン可能な場合は、醜いswitch文の代わりにstd::mapを使用できます。この代替方法は、Prototype Patternの例になります。このアプローチを示すサンプルコードを次に示します。

class WidgetFactory 
{ 
public: 
    QWidget* create(const std::string& name) { 
     return prototypes_[name]->clone(); 
    } 

    void addPrototype(const std::string& name, QWidget* prototype) { 
     prototypes_[name] = prototype; 
    } 

private: 
    std::map<std::string, QWidget*> prototypes_; 
} 


WidgetFactory factory; 
factory.addPrototype("DashBoard0", new DashBoard0); 
factory.addPrototype("DashBoard1", new DashBoard1); 


void addDashboard(QListWidgetItem* item) { 
    int index = listWidget->row(item); 

    QWidget* widget = factory.create(command.atIndex(index).getWidgetTypeName()); 
    widget->show(); 

} 

C++はあまり動的な言語ではありません。これはRTTI機能を制限しており、C#のリフレクション機能はほとんどありません。そのため、ファクトリメソッドや抽象ファクトリのようなパターンに頼らざるを得ません。


補遺

それはQtは簡単なユーティリティのアプリのためのC++(Iのみ使用Qtの中で通常利用可能なものを超えて、ランタイムクラス情報を提供するかもしれないことを私に夜が明けていないので、私はしないでくださいすべての鐘を知ってください&そのフレームワークで利用可能なホイッスル)。これを念頭に置いて、Qtオブジェクトをクラス名でインスタンス化する方法について、このメーリングリストdiscussionを検索して見つけました。しかし、その解決策がプラグインオブジェクトで動作するかどうかはわかりません。

+0

しかし、それはQWidget * test2 = new typeof(EmptyWorkspace)とどのように異なるでしょうか。またはテンプレート QWidget * testing(){return new T(); }これに?どのようにしてこの問題を解決することができますか?私がしたいのは、どのクラスをどのボタンに作成するかを定義するリストをロードすることだけです。ボタンがクリックされると、そのウィジェットが作成され、QStackedWidgetに追加されます。リストはクラスでパッケージにロードされるので、実行時に作成されます。 – chikuba

+1

私はスタンバイを説明するための小さなコードサンプルを書いています。 –

+0

typeofは実際にコンパイラの拡張機能であるコンパイル時の "関数"です。それはコンパイル時にある型にしか評価できません。あなたがC#から来ていると仮定すると、ランタイムリフレクションは使用できないので、あなたが使っているものの多くは不可能です。主な理由の1つは、パフォーマンスとスペースの問題、そしてそのようなシステムがあればコンパイラの実装を制限することです。私はこれを解決する良い方法について考えるでしょうが、ブルートフォースの方法は、巨大なswitch文を持ついくつかの関数であり、それぞれの型のケースでは、その特定の型の新しいインスタンスを返します。これは醜いです:P –

関連する問題