首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按名称检索对象的简单工厂

按名称检索对象的简单工厂
EN

Code Review用户
提问于 2015-12-20 21:54:13
回答 4查看 1.4K关注 0票数 6

尽管这段代码可以工作,但我想知道是否有什么情况我没有预料到,和/或我试图做的是什么错误。

-std=C++11标志需要

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <map>
#include <typeinfo>
#include <functional>

class object
{
    public:

    virtual ~object(){}

    virtual std::string to_string() = 0;
};

class SomeObject : public object
{
    public:

    SomeObject(){}
    virtual ~SomeObject(){}

    virtual std::string to_string()
    {
        return "I am a type of SomeObject";
    } 
};

class SomeOtherObject : public object
{
    public:

    SomeOtherObject(){}
    virtual ~SomeOtherObject(){}

    virtual std::string to_string()
    {
        return "I am a type of SomeOtherObject";
    } 
};

std::map<std::string, std::function<object*()> > types;

template<typename O>
inline
static void register_type(const std::string & name)
{
    types[name] = [](){ return new O; };
}

static object * get_object(const std::string & object_name )
{
    return types[object_name]();
}

int main()
{
    register_type<SomeObject>("SomeObject");
    register_type<SomeOtherObject>("SomeOtherObject");

    object * some = get_object("SomeObject");
    object * some_other = get_object("SomeOtherObject");

    std::cout << "::" << some->to_string() << std::endl;
    std::cout << "::" << some_other->to_string() << std::endl;

    delete some;
    delete some_other;

    std::cout << "exit" << std::endl;

    return 0;
}
EN

回答 4

Code Review用户

回答已采纳

发布于 2015-12-20 22:39:25

一般来说,您的代码看起来很好,尽管有一些需要改进的地方:

内存管理

与其使用原始指针和new delete,不如使用智能指针显式地表示所有权的传递:

代码语言:javascript
复制
template<typename O>
void register_type(const std::string & name) {
    types[name] = [](){ return std::unique_ptr<O>(new O); };
}

std::unique_ptr<object> get_object(const std::string & object_name ) {
    return types[object_name]();
}

因此很明显,调用方将拥有object实例,并且在获得的实例超出作用域时不需要正确调用delete

模板参数命名

模板参数更常见的名称是T而不是O

使用工厂类而不是全局函数和全局映射

register_type()get_object()函数和types映射变量的代码合并到一个class Registry中,并提供该实例的一个实例。

这将允许将types映射封装为私有类成员。

你可以考虑把那门课变成单身。

检查类型名称是否已注册

您应该检查传递给get_object()函数的字符串是否已经在映射中注册,而不是从映射中盲目地调用默认(NOP)函数。

全局函数

static的使用

您应该知道,static实际上使register_type()函数只对翻译单元可见,它出现在。其实你不应该需要它。

顺便说一句,您使用的技术通常用于单元测试框架(例如google- test )作为测试用例工厂,也经常伴随着注册类的字符串化宏。

票数 6
EN

Code Review用户

发布于 2015-12-20 22:24:08

  • 您不再需要std::map >type;^中的空间了。C++11已经了解到,在这种情况下,>>不是shift操作符。
  • 为什么register_type staticinline?我觉得这两个人都说不通。
  • 使用T作为模板参数类型是非常常见的,O不太常见,这使得代码很难阅读。
  • 返回原始的拥有指针在C++11中是不好的样式。请返回一个std::unique_ptr,因为它将在默认情况下防止泄漏。如果人们不喜欢它,他们可以调用.release(),所以您不会失去灵活性。
  • 有些人认为std::endl的风格很糟糕,因为它会冲淡输出,不必要地放慢程序的速度。
  • 也许您可以扩展register_type以接受非默认可构造的类型。
票数 4
EN

Code Review用户

发布于 2015-12-23 16:37:12

删除不必要的虚拟函数

在您的SomeObjectSomeOtherObject类中,您是否期望它们也会被继承?如果没有,则删除virtual并从C++11中使用override上下文关键字。这将允许您将覆盖toString()函数的意图显式化,并提供编译时检查,以确定是否真正覆盖正确的函数。在这个特定的例子中,这可能有些过分(因为它的简单性),但这是一个很好的习惯。您还可以删除这些类的默认ctors和dtors的不必要定义(因为编译器会自动为您提供它们)。

代码语言:javascript
复制
class object
{
    public:

    virtual ~object(){}

    virtual std::string to_string() = 0;
};

class SomeObject : public object
{
    public:

    std::string to_string() override
    {
        return "I am a type of SomeObject";
    } 
};

class SomeOtherObject : public object
{
    public:

    std::string to_string() override
    {
        return "I am a type of SomeOtherObject";
    } 
};

使用工厂注册表类/内存管理

正如其他人所提到的,将全局映射和注册表/取消注册函数转换为可以管理自己状态的类。此外,这里使用std::unique_ptr而不是运算符new

用std::unordered_map

替换std::map

看起来您不需要std::map给您的排序(以及相应的log(n)插入时间)。如果要查找哈希表(摊销的O(1)插入/检索),则使用std::unordered_map。

为非默认可构造对象

扩展register_type()

为此使用各种模板:

代码语言:javascript
复制
struct Registry
{

    template <class T, class... Args>
    static void register_type(const std::string &name, Args&&... args)
    {
        types[name] = [&args...]() { return std::make_unique<T>(std::forward<Args>(args)...); };
    }

    static std::unique_ptr<object> get_object(const std::string &name)
    {
        return types[name]();
    }

private:
    static std::unordered_map<std::string, std::function<std::unique_ptr<object>()>> types;
};
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/114578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档