C ++非堆使用受保护的构造函数和复制构造函数创建工厂对象

时间:2016-12-09 12:07:56

标签: c++ copy-constructor factory-pattern protected deleted-functions

由于RAII功能,我希望我的对象只能放在堆栈上,并且对象创建应该委托给专门的工厂,我不希望ocpy构造函数可以使用。

所以我做了类似的事。

template<typename Product, Args ... >
class Creator : public Product
{
    public:
        static Product create(Args ... args)
        {
            return Product(args ... );
        }
};

class ProtectedClass
{
        ProtectedClass(const ProtectedClass& aThat)=delete;
        ProtectedClass& operator=(const ProtectedClass& aThat)=delete;
    protected:
        ProtectedClass(){}
};

class Spawner
{
    public:
        ProtectedClass getProtectedClass()
        {
            return Creator<ProtectedClass>::create();
        }
}

int main()
{
    Spawner spawner;
    //I need protectedClass to be enclosed within this frame
    ProtectedClass protectedClass = spawner.getProtectedClass(); // err copy constructor is delted
}

我可以做这样的事情

template<typename Product, Args ... >
class Creator : public Product
{
    public:
        Creator(Args ... args) : product_(args ...){}
        Product& get() const
        {
            return product_;
        }
    private:
        Product product_;
};

class Spawner
{
    public:
        std::unique_ptr<Creator<ProtectedClass>> getProtectedClassCreator()
        {
            return new Creator<ProtectedClass>();
        }
}

int main()
{
    Spawner spawner;
    std::unique_ptr<Creator<ProtectedClass>> creator = std::move(spawner.getProtectedClassCreator());
    ProtectedClass& protectedClass = creator->get();
}

但它似乎看起来并不正确。

有什么其他方法可以解决这个问题?

1 个答案:

答案 0 :(得分:1)

The way I would do this would be to delete copies, enable moves and allow construction via any class that can create a construction key.

// forward declare any factories
class Spawner;

struct ProtectedClass
{
    class PermissionKey {
        // this is a private constructor
        PermissionKey() {};

        // make friends of the factories
        friend Spawner;
    };

    // all this is now public.
    // because we have declared a constructor, the default constructor
    // is deleted.    
    ProtectedClass(PermissionKey) {}

    // disable copies
    ProtectedClass(const ProtectedClass& aThat)=delete;
    ProtectedClass& operator=(const ProtectedClass& aThat)=delete;

    // enable moves so the factory can return it
    ProtectedClass(ProtectedClass&& aThat)=default;
    ProtectedClass& operator=(ProtectedClass&& aThat)=default;
};

class Spawner
{
public:
    ProtectedClass getProtectedClass()
    {
        // construct our spawned object - we can create keys
        return ProtectedClass(ProtectedClass::PermissionKey());
    }
};

int main()
{
    Spawner spawner;
    //I need protectedClass to be enclosed within this frame
    auto protectedClass = spawner.getProtectedClass(); // ok now
}