【问题标题】:C++ non heap Factory object creation with protected constructor and copy constructor使用受保护构造函数和复制构造函数创建 C++ 非堆工厂对象
【发布时间】:2016-12-09 12:07:55
【问题描述】:

由于 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();
}

但看起来不太对劲。

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

【问题讨论】:

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


    【解决方案1】:

    我这样做的方法是删除副本、启用移动并允许通过任何可以创建构造键的类进行构造。

    // 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
    }
    

    【讨论】:

    • 最后我选择了 unique_ptr。当 dtor 参与每一个移动操作时,会出现很多问题。
    • @user1079475 你比我更了解用例。但我以为你想要堆栈上的对象?
    • 是的,我做到了,但是将对象从方法范围移动到调用范围时太麻烦了。这些对象具有互斥体属性,并且需要在堆上移动这些互斥体等等。麻烦多多收效甚微
    猜你喜欢
    • 2013-04-29
    • 2020-08-16
    • 2018-02-03
    • 2011-05-30
    • 2021-06-10
    • 2023-03-15
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    相关资源
    最近更新 更多