C++ Назначение этого указателя класса на unique_ptr или shared_ptr
У меня есть базовый класс, от которого я хочу наследовать, и до того, как любой из его производных классов может быть объявлен, по крайней мере 1 экземпляр базового класса должен быть объявлен первым. Я думал о хранении this pointer
базового класса в свою собственную переменную-член уникального_птр вместо использования 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) в умный указатель любого типа? Я предпочел сделать уникальное, где родительский класс "владеет" своим собственным указателем.
Если вам нужна дополнительная информация, пожалуйста, дайте мне знать, и я обновлю этот вопрос по запросу, например, показывая определение конструктора моего базового класса.
1 ответ
Лучшее, что вы можете сделать, - это использовать модель с навесом.
Вы создадите каждый класс один раз (используя std::shared_ptr
кажется наиболее разумным), но тогда вы будете использовать легкий класс для инкапсуляции каждого класса, который заменяет классы, которые вы создаете только один раз, т.е. вы создадите, скажем, класс Parent и Child (без иерархии наследования), а затем передадите их в ParentFlyweight и ChildFlyweight, где ChildFlyweight наследуется от ParentFlyweight.