2017-12-28 25 views
0

TOwnedCollection/TCollectionItemを使用してコレクションまたはリストを実装したいとします。多態性を持つクラスの永続的なリスト(FileStreamから読み込んで作成する)が必要です。2倍の派生クラスTCollectionItemをTOwnedCollectionに追加するにはどうすればよいですか?

ここまでは私のコードの一部ですが、親TPowerComponentの代わりに派生クラスTGeneratorを作成してコレクションに追加できませんでした。

//------------------------------------------------------------------------------------- 
class TPCCollection : public TOwnedCollection 
    { 
      typedef TOwnedCollection inherited; 
    private: 
      TPowerComponent* __fastcall GetPowerComponent(int Index); 
      void __fastcall SetPowerComponent(int Index, TPowerComponent *Value); 

    public: 
      __fastcall TPCCollection(TPersistent *Owner); 

      HIDESBASE TPowerComponent* __fastcall Add(void); 
      HIDESBASE TPowerComponent* __fastcall Insert(int Index); 

      __property TPowerComponent* PCCollection[int Index] = {read=GetPowerComponent, write=SetPowerComponent}; 
}; 

//------------------------------------------------------------------------------------- 
class TPowerComponent : public TCollectionItem 
{ 
    typedef TCollectionItem inherited; 
public : 
    int X, Y, Rotation; 
    PowSymbType HisType; 

    __fastcall TPowerComponent(TCollection *Collection, PowSymbType AType); 
    void __fastcall Assign(TPersistent *Source); 
    virtual void __fastcall Paint(TCanvas * Canvas); 
}; 
//------------------------------------------------------------------------------------- 
class TGenerator : public TPowerComponent 
{ 
      typedef TPowerComponent inherited; 
public : 
    double PG, Qgmin, Qgmax, Vsch; 

    __fastcall TGenerator(TCollection *Collection, PowSymbType AType); 
    void __fastcall Assign(TPersistent *Source); 
    virtual void __fastcall Paint(TCanvas * Canvas);  
    }; 
//------------------------------------------------------------------------------------- 
// implementation 
//------------------------------------------------------------------------------------- 
// TPCCOllection 
//------------------------------------------------------------------------------------- 
__fastcall TPCCollection::TPCCollection(TPersistent *Owner) 
     : TOwnedCollection(Owner, __classid(TPowerComponent)) 
{ 
} 
//------------------------------------------------------------------------------------- 
TPowerComponent* __fastcall TPCCollection::Add() 
{ 
    return static_cast<TPowerComponent>(inherited::Add()); 
} 
//------------------------------------------------------------------------------------- 
TPowerComponent* __fastcall TPCCollection::Insert(int Index) 
{ 
    return static_cast<TPowerComponent>(inherited::Insert(Index)); 
} 
//------------------------------------------------------------------------------------- 
TPowerComponent* __fastcall TPCCollection::GetPowerComponent(int Index) 
{ 
    return static_cast<TPowerComponent>(inherited::GetItem(Index)); 
} 
//------------------------------------------------------------------------------------- 
void __fastcall TPCCollection::SetPowerComponent(int Index, TPowerComponent *Value) 
{ 
    inherited::SetItem(Index, Value); 
} 
//------------------------------------------------------------------------------------- 
// TPowerComponent 
//------------------------------------------------------------------------------------- 
__fastcall TPowerComponent::TPowerComponent(TCollection *Collection, PowSymbType AType) 
     : TCollectionItem(Collection) 
{ 
    HisType=AType; 
    Rotation=0; 
} 
//------------------------------------------------------------------------------------- 
void __fastcall TPowerComponent::Assign(TPersistent *Source) 
{ 
    TPowerComponent *Src = dynamic_cast<TPowerComponent>(Source); 
    if(Src) 
     { 
       // copy members from Src... 
     } 
    else inherited::Assign(Source); 
} 
//------------------------------------------------------------------------------------- 
// se dessine 
void __fastcall TPowerComponent::Paint(TCanvas * Canvas) 
{ 
... 
} 
//------------------------------------------------------------------------------------- 
// TGenerator 
//------------------------------------------------------------------------------------- 
__fastcall TGenerator::TGenerator(TCollection *Collection, PowSymbType AType) 
     :TPowerComponent(Collection, AType) 
{ 
    PG=0; Qgmin=0; Qgmax=0; Vsch=1.0; Con=-1; 
} 
//------------------------------------------------------------------------------------- 
void __fastcall TGenerator::Assign(TPersistent *Source) 
{ 
    TGenerator *Src = dynamic_cast<TGenerator>(Source); 
    if(Src) 
     { 
       // copy members from Src... 
     } 
    else inherited::Assign(Source); 
} 



//------------------------------------------------------------------------------------- 
// Usage 
TPCCollection * NetWork = new TPCCollection(this); 

// Usage to Access all the collection 
for(int i=0; i< NetWork->Count; i++) 
    { 
    ((TPowerComponent*)(NetWork->Items[i]))->Paint(Canvas); 
    } 

TGeneratorなくTPowerComponentを追加するには、私が使用:

TGenerator * Gen=new TGenerator(NetWork, Generator); 

TCollectionItemの子の作成自動的に「ここでの問題は、私たちができることであるTCollectionの

に自分自身を追加アイテムの作成プロセスをコレクションに追加しないようにします。

たとえば、最初のコレクションリストの項目のいくつかを持つことができる別のリストが必要な場合、SelectedComponentsは、それらを再作成せずにNetWork Collectionの項目の1つまたはいくつかを持つことができます。

これは

std::list<TPowerComponent*> SelectedComponents; 

で行うことができますが、私は、FileStreamを/永続的なリストを使用してそれらを読む/書くことはできません。私はそれらを再作成せずにTCollectionに入れる必要があります。

どのようにですか?

+0

司会者の推奨を満たすために私の質問を編集しました – Lotfi

答えて

1

TCollectionのRTLのネイティブDFMストリーミングは、多態的なTCollectionItemクラスを部分的にしかサポートしません。

多型のTCollectionItemオブジェクトは、渡される共通の基底クラスから派生するものであれば、コード内で(実行時にもカスタムエディタを使用してデザイン時にも)コード内でTCollectionに追加できますTCollectionコンストラクタ。そのようなコレクションは、そのままDFMに保存することもできます。バックDFMをロードするときに

しかし、ネイティブのストリーミングを使用すると、TCollectionコンストラクタに渡すどんなTCollectionItemクラス型を使用するDFMから読み込まれ、すべてのコレクションアイテムを強制します。したがって、ポリモーフィッククラスはネイティブにロードできません。

その動作をオーバーライドする唯一の方法は、(あなたのTCollectionプロパティはpublished非可能にする、または少なくともstored=falseとしてマーク)収集のためにネイティブのストリーミングを無効にしてから、手動でコレクションアイテムをストリーミングすることです。

あなたの主なコンポーネント(または何TPersistentクラスは、コレクションを所有している)を持っては、コレクションアイテムをストリーミングするためのカスタム読み込み/書き込みメソッドを登録するTFiler.DefineProperty()を呼び出すために仮想DefineProperties()メソッドをオーバーライドします。ポリモーフィッククラスをサポートするには、プロパティ値を書き込む前に各アイテムのClassNameをDFMに書き込んでから、名前を読み取ってプロパティ値を読み込む前にどのクラスをインスタンス化するかを知る必要があります。

+0

私のTPowerComponentとそれらの子はTボタンのようなTFormの一部ではありません。そうすれば、TCollection/TCollectionItemクラスを扱う必要はありませんそれら?それらをストリームに書き込むことはできますか?しかし、ストリームからオブジェクトを読み込むとき(手動)、それがどの子供(TGenerator、TLoad、TLIne ...)であるかを知ることができますか? – Lotfi

+1

デザインタイム編集やDFMストリーミングをサポートしない限り、 'TCollection' /' TCollectionItem'を使う必要はありません。ストリーミングに関しては、私が答えて言ったように、値を書き込む前に子クラスのクラス型の名前をストリームに書き込む必要があります。ストリームを読み戻すときには、子のクラスの型名を最初に読み込んで、その値を読み取る前にその子をインスタンス化するクラスを知る必要があります。 –

関連する問題