首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >根据值实例化不同对象类型的最佳方式?

根据值实例化不同对象类型的最佳方式?
EN

Stack Overflow用户
提问于 2013-05-13 16:50:32
回答 1查看 318关注 0票数 6

我将把我的数百个类的问题简化为两个,并尝试解释我的意思:

代码语言:javascript
运行
复制
class Base {
};
class A: public Base {
};
class B: public Base{
};

static Base* foo (int bar){

    switch (bar) {
        case 0:
            return new A();
            break;              
        case 1:
            return new B();
            break;
        default:
            return new Base();
    }
}

我想根据bar的值来实例化对象。我只是觉得对于更多的Base继承者来说,在C++中切换大小写并不是最好的方式。

编辑:按照我提出的std::map方法:

代码语言:javascript
运行
复制
struct Dictionary {
    typedef Base* (Dictionary::*FunctionPointer)(void);
    std::map <int, FunctionPointer> fmap;

    Dictionary() {
        fmap.insert(std::make_pair(0, new A()));
        fmap.insert(std::make_pair(1, new B()));
    }

    Base* Call (const int i){
        FunctionPointer fp = NULL;
        fp = fmap[i];
        if (fp){
            return (this->*fp)();
        } else {
            return new Base();
        }
    }
};

static Dictionary dictionary;
EN

Stack Overflow用户

回答已采纳

发布于 2013-05-13 17:17:43

这在很大程度上取决于环境,但最常见的解决方案可能是使用映射到工厂函数的静态实例。如果map的键类型是一个小整数值,如您的示例所示,那么"map“只能是一个C样式的数组:

代码语言:javascript
运行
复制
static Base*
foo( int bar )
{
    static Base* (*factories[])() = [ &aFactory, &bFactory ];
    return bar >= 0 && bar < size( factories )
        ? (*factories[bar])()
        : baseFactory();
}

更一般地,您可以使用std::map (用于区分任何可以想象的类型),并且如果不同的键应该产生相同的类型,但具有不同的参数,则可以映射到工厂对象的静态实例,而不是工厂函数。

编辑:

以下是一些改进Dictionary::Call功能的建议:

代码语言:javascript
运行
复制
Base* Dictionary::Call( int i ) const
{
    std::map<int, FunctionPointer>::const_iterator
                        entry = fmap.find( i );
    return entry == fmap.end()
        ? new Base()
        : (this->*(entry->second))();
}

我使用了const函数,因为它不修改任何东西,而且最重要的是,我使用了std::map<>::find,以避免在映射中插入额外的条目(如果对象不在映射中)。

由于我添加的是const,因此您必须更新typedef:

代码语言:javascript
运行
复制
typedef Base* (Dictionary::*FunctionPointer)() const;

另一个建议:除非工厂函数需要访问Dictionary,否则将它们设为静态的。语法要简单得多(而且可能还会提高性能)。static再次更改了typedef:

另外:在构造函数中,new A()不是构造新对象的函数。在C++11中(在lambda和std::function之间)可能有一些东西可以促进这一点,但除此之外,您仍然必须手动编写每个工厂函数。或者,您可以使用模板:

代码语言:javascript
运行
复制
template <typename Target>
Base* construct() const
{
    return new Target();
}

Dictionary()
{
    fmap.insert( std::make_pair( 0, &Dictionary::construct<A> ) );
    //  ...
}

或者,如果您将它们设为静态:

代码语言:javascript
运行
复制
typedef Base* (*FunctionPointer)();

//  ...
template <typename Target>
static Base* construct()
{
    return new Target();
}

Base* Dictionary::Call( int i ) const
{
    std::map<int, FunctionPointer>::const_iterator
                        entry = fmap.find( i );
    return entry == fmap.end()
        ? new Base()
        : (*entry->second)();
}

您将注意到static如何简化声明(以及通过指针调用函数-指向成员函数的指针变成了指向函数的简单指针)。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16518065

复制
相关文章

相似问题

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