2017-01-16 3 views
0

私は、派生クラスのいずれかを宣言する前に継承したい基本クラスを持っています。少なくとも1つの基本クラスのインスタンスを先に宣言しなければなりません。私は、基本クラスのthis pointerstatic_ptrの代わりに独自のメンバ変数unique_ptrに格納することを考えていました。また、基本クラスは、別の基本クラスが宣言されるまで、派生クラスのすべてのインスタンスを追跡します。すべての派生型のような、このベースから公に継承しますC++ unique_ptrまたはshared_ptrのいずれかにこのポインタを代入する

#include <vector> 
#include <map> 
#include <memory> 
#include <string> 

class Parent { 
public: { 
    enum ChildType { 
     CHILD_NONE = 0, 
     CHILD_A, 
     CHILD_B, 
     CHILD_C, 
    }; // ChildType 

protected: 
    ChildType type_; // Type of Child Class when inheritance is used 
    std::string childName_; // Name of Child Class when inheritance is used 

private: 
    const std::string myName_; // Name of this parent class 
    bool parentConstructed_ = false; // Flag if this parent was constructed 

    const static Parent* s_firstParent_; // static pointer 
    std::unique_ptr<Parent> me_; // Or 
    std::shared_ptr<Parent> me_; 

    // Some Typedefs for containers 
    typedef std::vector<std::shared_ptr<Parent>> Children; 
    typedef std::vector<std::shared_ptr<Parent>> OtherParents; 
    typedef std::vector<std::shared_ptr<Parent>> Siblings; 

    typedef std::vector<std::string> Names; 
    typedef Names ChildrenNames, OtherParentsNames, SiblingsNames; 

    // Containers and map associations of names. 
    Children children_; 
    ChildrensNames namesOfChildren_; 
    std::map< ChildrensNames, Children > mapChildren_; 

    OtherParents otherParents_; 
    OtherParentsNames associatedParentsNames_; 
    std::map< OtherParentsNames, OtherParents > mapParents_; 

    Siblings siblings_; 
    SiblingsNames namesOfSiblings_; 
    std::map< SiblingsNames, Siblings > mapSiblings_; 

public: 
    // This constructor must be called at least once as a base class instantiation 
    // Before Any of its derived members can be declared. 
    explicit Parent(const std::string& parentName); 

    // Other necessary constructors and operators for move semantics 
    Parent(Parent &&self); 
    Parent& operator=(Parent &transfer); 

    Parent(Parent const&) = delete; 
    Parent& operator=(Parent const &) = delete; 

    // Other functions that are part of the public interface that 
    // may be overridden by the inherited types 
    virtual void printName() const; 
    const std::string& getName() const; 

    // Other public methods that are common among all types including 
    // derived and base types. 

protected: 
    // Constructor Signature to be Used for Derived Types 
    Parent(const std::string& parentName, std::string& childName, ChildType type); 

    // Other Protected Members for use with derived types 
}; 

:ここに私のクラス宣言がどのように見えるかです

class ChildA : public Parent { 
public: 
    ChildA(const std::string& parentName, std::string& myName, ChildType type); 
}; 

私は私のメインの中で、このクラス階層を使用するための心の中に持っているアイデアを希望

#include "ChildA.h" 
#include "ChildB.h" 
#include "ChildC.h" 

int main() { 
    // If we try to do this: 
    ChildA a(std::string("Parent"), std::string("ChildA"), Parent::ChildType::CHILD_A); 
    // The Last parameter would not be needed to be set since that would 
    // be done automatically by default for all derived types, but just shown here for demonstrative purposes. 

    // This construction of derived type would throw an exception because at 
    // least one base was not declared. 

    // This must be done first: 
    Parent parent(std::string("Parent1"); 
    // Then this would be valid 
    ChildA a(std::string("Parent1"), std::string("ChildA")); 
    ChildB b(std::string("Parent1"), std::string("ChildB")); 

    // Then if we created a 2nd parent base 
    Parent parent2(std::string("Parent2"); 
    // The next set of child classes might be nested under this parent since 
    // it is a 2nd instance and the name doesn't match. 
    // if one was to call this constructor above as is but passed in 
    // the same string as from a previous instance it would also throw an exception. 

    // In this next line of code it would not necessarily be nested automatically 
    // to Parent2 because it would check the string name passed in for the 
    // parents name and nest it accordingly if it found that string. 
    ChildC c(std::string("Parent1 or 2"), std::string("ChildC"));   

    return 0;  
} 

私は実行時に、それのインスタンスを1つだけ持っているクラスからこのポインタを取得するには、静的関数で静的ポインタを作成する方法を知っていますが、以下のようになります応用。私はちょうどshared_ptrまたはunique_ptrを代わりに使用し、ベースタイプの少なくとも1つのインスタンスを最初に作成した後、どちらかのタイプのスマートポインタに(this)ポインタを保存することを知りたいのですか?私は、親クラスが自身のポインタを所有しているところでユニークな作業をすることを好みました。

さらに詳しい情報が必要な場合は、私に知らせてください。この質問は、基本クラスのコンストラクターの定義を表示するなど、必要に応じて更新します。

+1

あなたは継承する 'std :: enable_shared_from_this'が必要で、クラスに' shared_from_this'関数を与えて、 'this'を指す' shared_ptr'を取得します。 – Donnie

+0

@Donnie私はそれをやろうとしましたが、 'syntax 'を間違えていない限り、それはまだ動作していないか、コンパイルしていませんでした。 –

+0

@Donnieは、コ​​ンストラクタの正しい構文は次のようになります: 'me_.reset(std :: enable_shared_from_this :: shared_from_this());'または 'me_ = std :: enable_shared_from_this :: shared_from_this();'?これを使うのはちょっと新しいです。今見たように、これは 'shared_ptr'のために働きますが、' unique_ptr'でも同様の仕組みがありますか? –

答えて

1

あなたができることは、flyweightパターンを使用することです。

std::shared_ptrを使用して各クラスを1回作成しますが、軽量クラスを使用して、作成するクラスを表すクラスをカプセル化します。つまり、親と子を作成します(継承階層はありません)、ChildFlyweightがParentFlyweightから継承するParentFlyweightおよびChildFlyweightに渡します。

+0

私はリンクを読んで、 'Parent'クラスに関連のすべてのコンテナを追跡する代わりに' Parent-Child'クラスをもう少しシンプルにしてから、マネージャーアプリケーションの実行ごとに1つのインスタンスしか利用できない場合は、クラスインスタンスとアソシエーションを追跡するのはこの3番目のクラスの責任となります。 –

+0

はい、フライウェイトパターンを使用すると、通常、仲介者として機能するクラスが作成されます。 – keith

関連する問題