以支持继承的方式将shared_ptr添加到self到对象构造函数中的vector

时间:2018-06-27 15:22:54

标签: c++ pointers vector memory-management

我希望在创建对象时将对创建对象的引用自动添加到一个矢量(通常是多个矢量)中。为了提供一些背景信息,此代码将在游戏中用于游戏对象集(可绘制,可碰撞,敌人等),因此需要多个向量。

下面是我要实现的目标的示例:

#include <iostream>
#include <memory>
#include <vector>
class BaseClass :public std::enable_shared_from_this<BaseClass>
{ //for example "drawable"
public:
    BaseClass()
    {
        std::cout << "Base Created"<<std::endl;
        BaseList.push_back(shared_from_this());//I want to put a reference to this object in a vector
    }
    ~BaseClass()
    {
        std::cout << "Base Deleted"<<std::endl;
    }
    static std::vector<std::shared_ptr<BaseClass>> BaseList;

};
class DerivedClass :public BaseClass
{//for example "enemy"
public:
    static std::vector<std::shared_ptr<BaseClass>> DerivedList; //shared_ptr of baseclass can point to derivedclass
    DerivedClass()
    {
        std::cout << "Derived Created" << std::endl;
        DerivedList.push_back(shared_from_this());//reference to this object in a vector in addition to the other vector
    }
    ~DerivedClass()
    {
        std::cout << "Derived Deleted" << std::endl;
    }
};
std::vector<std::shared_ptr<BaseClass>> BaseClass::BaseList;
std::vector<std::shared_ptr<BaseClass>> DerivedClass::DerivedList;
int main()
{

    std::shared_ptr<BaseClass> C = std::make_shared<BaseClass>();
    std::shared_ptr<BaseClass> D = std::make_shared<DerivedClass>();

    BaseClass::BaseList.clear(); //C should be deleted, D should not since it is still in DerivedList
    DerivedClass::DerivedList.clear(); //now D should be deleted
    return 0;
}

在此代码中,shared_from_this()的使用不正确,因为它在构造函数(As Shown Here)中。以前,我已经使用单独的静态函数克服了这个问题,例如:

void BaseClass::makeOne()
{
    std::shared_ptr<BaseClass> P(new BaseClass());
    BaseClass::BaseList.push_back(P);
}

void DerivedClass::makeOne()
{
    std::shared_ptr<BaseClass> P(new DerivedClass());
    BaseList.push_back(P);
    DerivedList.push_back(P);
}

但是,在从一个基类派生多个类并且每个派生类也可以添加到其他向量的情况下,代码重复成为一个问题({BaseList.push_back(P)应该为继承{ {1}},因此必须写在BaseClass继承X::MakeOne()的每个X中)。

我也通过简单地使用原始指针(BaseClass)克服了这个问题,但是当在多个地方引用对象时,这失去了简单的内存管理和引用计数的好处。在这种情况下是否有更好的内存管理选项?

2 个答案:

答案 0 :(得分:1)

我认为可以通过使用Factory / Provider来解决。

class SomeBaseClass // Could also be an interface or similar
{
};

// Instead of having SomeBaseClassFactory instance, all the methods could also be static
class SomeBaseClassFactory
{
public:
    std::vector<std::shared_ptr<SomeBaseClass>> someBaseClassList;

    std::shared_ptr<SomeBaseClass> GenerateObject(/* Parameters */)
    {
        std::shared_ptr<SomeBaseClass> someBaseClass = std::make_shared<SomeBaseClass>(/* Parameters */);
        RegisterObject(someBaseClass);
        return someBaseClass;
    }

protected:
    void RegisterObject(std::shared_ptr<SomeBaseClass> objectToRegister)
    {
        someBaseClassList.push_back(objectToRegister);
    }
};

class SomeDerivedClass : public SomeBaseClass
{
};

class SomeDerivedClassFactory : public SomeBaseClassFactory
{
public:
    std::shared_ptr<SomeDerivedClass> GenerateObject(/* Parameters */)
    {
        std::shared_ptr<SomeDerivedClass> someDerivedClass = std::make_shared<SomeDerivedClass>(/* Parameters */);
        RegisterObject(someDerivedClass);
        return someDerivedClass;
    }
};

答案 1 :(得分:1)

您可以像这样为对象定义工厂:

#include <iostream>
#include <memory>
#include <vector>

class Factory
{
public:
    template<class T, class ... Args>
    static std::shared_ptr<T> Make(Args... args)
    {
        auto instance = std::shared_ptr<T>(new T(args...));
        T::List.push_back(instance);
        return instance;
    }
};

class BaseClass
{ 
    friend class Factory;  
protected:    
    BaseClass()
    {
        std::cout << "Base Created"<<std::endl;
    }

public:
    virtual ~BaseClass()
    {
        std::cout << "Base Deleted"<<std::endl;
    }

    static std::vector<std::shared_ptr<BaseClass>> List;

};
class DerivedClass : public BaseClass
{//for example "enemy"
    friend class Factory;  

    DerivedClass()
    {
        std::cout << "Derived Created" << std::endl;
    }
public:
    ~DerivedClass()
    {
        std::cout << "Derived Deleted" << std::endl;
    }

    static std::vector<std::shared_ptr<BaseClass>> List; //shared_ptr of baseclass can point to derivedclass
};

std::vector<std::shared_ptr<BaseClass>> BaseClass::List;
std::vector<std::shared_ptr<BaseClass>> DerivedClass::List;

int main()
{
    auto base = Factory::Make<BaseClass>();
    auto derived = Factory::Make<DerivedClass>();
}