C ++将类的指针分配给unique_ptr或shared_ptr

时间:2017-01-16 17:18:25

标签: c++ inheritance smart-pointers this-pointer

我有一个我想继承的基类,在它的任何派生类可以被声明之前,必须首先声明基类的一个实例。我在考虑将基类的this pointer存储到unique_ptr的自己的成员变量中,而不是使用static_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;    
}

我知道如何使用静态函数创建一个静态指针,以便在应用程序运行时期间从类中获取此指针,使其只有一个实例。我只是想知道是否有使用shared_ptr或unique_ptr而是在成功创建至少一个基本类型的实例之后,然后将(this)指针保存到任一类型的智能指针中?我更喜欢在父母班级拥有的地方做一个独特的&#34;它自己的指针。

如果您需要更多信息,请告诉我们,我会按要求更新此问题,例如显示我的基类构造函数的定义。

1 个答案:

答案 0 :(得分:1)

您可以做的最好的事情是使用flyweight模式。

您将创建每个类一次(使用std::shared_ptr似乎最合理),但是您将使用一个轻量级类来封装代表您只创建一次的类的每个类,即您将创建一个说父类和子类(没有继承层次结构),然后将它们传递给ParentFlyweight和ChildFlyweight,其中ChildFlyweight继承自ParentFlyweight。