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 ++使派生类只能从工厂/基类实例化的主要内容,如果未能解决你的问题,请参考以下文章