c++ - 工厂内专力级施工
问题描述
我想知道是否有人知道强制类层次结构只能由工厂构造的方法,从而有效地禁止在std::make_shared
该工厂之外直接使用。
在下面的示例中,我将Node作为基类,将SceneNode作为众多派生类之一。Node包含一个静态成员函数create(),它应该是工厂,并且是创建Node派生类的新实例的唯一方法。
#include <iostream>
#include <memory>
class Node {
public:
template <class T, class... Args>
static std::shared_ptr<T> create(Args&&... args)
{
static_assert(std::is_base_of<Node, T>::value, "T must derive from Node");
std::shared_ptr<T> node = std::make_shared<T>(std::forward<Args>(args)...);
return node;
}
protected:
Node() {}
};
class SceneNode : public Node {
public:
SceneNode() : Node()
{
}
};
int main() {
auto a = Node::create<SceneNode>(); // Should be the only way
auto b = std::make_shared<SceneNode>(); // Should be forbidden
}
解决方案
使您的工厂成为唯一能够实例化给定类的类的经典方法是使您的类构造函数私有,并使您的工厂成为您的类的朋友:
class Foo
{
friend class FooFactory;
private:
Foo() = default;
};
class FooFactory
{
public:
static Foo* CreateFoo() { return new Foo(); }
static void DestroyFoo(Foo* p_toDestroy) { delete p_toDestroy; }
};
int main()
{
// Foo foo; <== Won't compile
Foo* foo = FooFactory::CreateFoo();
FooFactory::DestroyFoo(foo);
return 0;
}
编辑(有一些继承):
#include <type_traits>
class Foo
{
friend class FooBaseFactory;
protected:
Foo() = default;
};
class Bar : public Foo
{
friend class FooBaseFactory;
protected:
Bar() = default;
};
class FooBaseFactory
{
public:
template <typename T>
static T* Create()
{
static_assert(std::is_base_of<Foo, T>::value, "T must derive from Foo");
return new T();
}
template <typename T>
static void Destroy(T* p_toDestroy)
{
static_assert(std::is_base_of<Foo, T>::value, "T must derive from Foo");
delete p_toDestroy;
}
};
int main()
{
// Foo foo; <== Won't compile
Foo* foo = FooBaseFactory::Create<Foo>();
FooBaseFactory::Destroy<Foo>(foo);
// Bar bar; <== Won't compile
Bar* bar = FooBaseFactory::Create<Bar>();
FooBaseFactory::Destroy<Bar>(bar);
return 0;
}
推荐阅读
- c# - 图像编码为 ccitt 的 iOS pdf
- spring - SpringBoot 2.0.1 中未提供执行器 /refresh
- django - 为什么我不能在 Django 的同一迁移中为组分配新权限
- machine-learning - ALS(交替最小二乘)算法在用户的多个排名中
- sql - 如何使用oracle sql获取多列中的第一个非零/非空值和最后一个零/非空值
- angular - Angular 项目中无法识别的功能
- nginx - 使用 ansible 启动 nginx 网络服务器:localhost:8080 没有响应
- java - 如何在 Java Swing 文本窗格中组合从左到右和从右到左的文本?
- extjs - EXTJS 5:选项卡面板上的自定义 UI 不起作用
- vue.js - 如何在 Nuxt 中导入 vue-full-calendar 作为插件