C++ Assigning this pointer of a class to either a unique_ptr or a shared_ptr

﹥>﹥吖頭↗ 提交于 2019-12-12 03:56:45

问题


I have a base class that I want to inherit from and before any of its derived classes can be declared at least 1 instance of the base class must be declared first. I was thinking about storing the this pointer of the base class into its own member variable of a unique_ptr instead of using a static_ptr. Also the base class will keep track of all instances of its derived classes until another base class is declared. Here is what my class declarations look like:

#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
};

All derived types will inherit publicly from this base such as:

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

The idea I have in mind for using this class hierarchy in my main would be as follows

#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;    
}

I do know how to create a static pointer with a static function to get the this pointer from the class to have only one instance of it during the runtime of the application. I just want to know is there away to use a shared_ptr or a unique_ptr instead and after successfully creating at least one instance of a base type first then saving the (this) pointer into either type of smart pointer? I was preferring to do a unique where the parent class "owns" it's own pointer.

If you need more information please let me know and I'll update this question as requested, such as showing my base class's constructor's definition.


回答1:


The best you can do is using the flyweight pattern.

You will create each class once (using std::shared_ptr seems most sensible), but then you will use a lightweight class to encapsulate each class that stands in for the classes you are only creating once i.e. you will create say a Parent and Child class (no inheritance hierarchy) and then pass those to ParentFlyweight and ChildFlyweight where ChildFlyweight inherits from ParentFlyweight.



来源:https://stackoverflow.com/questions/41681691/c-assigning-this-pointer-of-a-class-to-either-a-unique-ptr-or-a-shared-ptr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!