C ++使派生类只能从工厂/基类实例化

Posted

技术标签:

【中文标题】C ++使派生类只能从工厂/基类实例化【英文标题】:C++ Make derived class instantiable only from factory / base class 【发布时间】:2021-11-27 18:27:02 【问题描述】:

我正在建模类来表示具有子模块的模块等等。我使每个子模块都从基类(模块)派生。

但现在我想让除了某些特定方法(如工厂模式)之外的任何地方都无法创建子模块 - 以便为子模块提供一些配置。见代码:

class Module

    public:
        template<typename T, typename... Args>
        std::shared_ptr<T> addSubModule(Args&&... args)
        
            std::shared_ptr<T> module = std::make_shared<T>(args...);

            children.emplace_back(module);
            module->parent = this;

            return module;
        

    protected:
        Module* parent = this;
        std::vector<std::shared_ptr<Module>> children;
;


class SomeSubModule : public Module

    public:
        SomeSubModule(int param1, int param2)
        
            // ... some init
        
;


void Usage()

    Module rootModule;

    rootModule.addSubModule<SomeSubModule>(1, 2);   // <-- Way 1) This is what I want
    SomeSubModule sub(1, 2);                        // <-- Way 2) This also works, but I want to prevent it

我想让“方式 1”成为唯一的方式(这样我就可以在 addSubModule 中执行一些初始化操作,例如将新创建的模块添加到子向量中,初始化父指针等)。 我写它的方式,“方式 2”仍然是可能的,我不想要它。

【问题讨论】:

【参考方案1】:

一般来说,当我们想要控制一个类的构造时(比如说,它只使用智能指针分配堆,从不声明为本地值),您可以通过不公开构造函数来做到这一点!

构造函数应该是非公开的,并且只能由应该使用它的其他代码访问。简单的方法是使用friend。在 Boost 中,您可以找到更复杂的方法,例如声明另一种类型作为访问路径,这对于处理大量子模块非常方便。

【讨论】:

类似 class Module class submodule...; ; 这样的东西在 C++ 中会是一个好的设计模式吗? 使submodule 成为Module 的成员会使使用所需的语法变得很尴尬。组织名称与问题和解决方案无关,所以也许你认为这是在做某事......? @JDługosz 所以你的意思是,每个子模块类都必须将其构造函数设为私有/受保护,然后将Module 声明为他们的朋友。这是一种可能性。问题是保护留给子模块的作者,并受制于他对这种必要性的了解。您可以将Module 视为其他人将使用的框架/库。我一直在寻找一些优雅的解决方案,这种“保护”会自动施加,例如通过继承Module 你能指出 Boost 的特殊情况吗?也许我可以看看他们是如何实现的。 正确的解决方案(+1),但可以用一个例子来演示。也许是一个快速的 hack,可以演示您使用工厂函数描述的内容。

以上是关于C ++使派生类只能从工厂/基类实例化的主要内容,如果未能解决你的问题,请参考以下文章

工厂方法(创建型)

c++实例化一个对象

派生类型的自动静态调用

大话设计模式------简单工厂模式

设计模式之工厂模式

PHP设计模式 -- 工厂模式