【问题标题】:object factory for overloaded functions重载函数的对象工厂
【发布时间】:2016-10-08 05:38:35
【问题描述】:

通常,对象工厂通过调用来创建类的实例

auto world = ObjectFactory::instance()->create("MatrixTransform");
auto cube1 = ObjectFactory::instance()->create("Cube");
auto sphere = ObjectFactory::instance()->create("Sphere");

它使用没有参数的已注册函数的映射,例如 Node 类是 MatrixTransformCubeSphere 类的基类:

// Map of registered factory functions
std::map<std::string, std::function<Node *(void)>> functionRegistry;

现在,我想注册带有有限数量参数(一个或两个)的重载构造函数,例如MatrixTransform(std::string objectName)MatrixTransform(std::string objectName, glm::mat4 matrixTransform),这样我不仅可以调用

auto world = ObjectFactory::instance()->create("MatrixTransform");

还有

auto world = ObjectFactory::instance()->create("MatrixTransform", "world");

甚至

auto world = ObjectFactory::instance()->create("MatrixTransform", "world", "glm::mat4())");

我知道可以将具有不同签名的函数存储在映射中,这意味着函数具有不同的参数和/或返回类型,但是如何注册不仅具有不同签名而且具有相同名称的函数,例如鉴于地图中的键必须是唯一的,因此不能重复,所以上面重载了构造函数?如果需要,可以发布整个对象工厂代码。谢谢!

【问题讨论】:

  • 你确定这没有被过度设计吗?在没有工厂的情况下直接创建对象真的有优势吗?在您的示例中,我看不到工厂如何击败简单的auto world = new MatrixTransform(glm::mat4())。我只是考虑使用std::unique_ptr&lt;Node&gt; 而不是Node*
  • @Christian Hackl 我有大量的类共享同一个基类,并且需要在运行时创建特定的实例,所以我开始研究对象工厂模式。当然,最终会使用std::unique_ptr&lt;Node&gt; 而不是Node*

标签: c++ stl operator-overloading factory


【解决方案1】:

如果您接受使用枚举类,则不必为此使用地图:

#include<utility>
#include<string>

enum class Type { MatrixTransform, Cube, Sphere };

template<Type>
struct tag {};

struct Factory {
    template<Type T, typename... A>
    static auto create(A&&... args) {
        return create(tag<T>{}, std::forward<A>(args)...);
    }

private:
    static auto create(tag<Type::MatrixTransform>) {}
    static auto create(tag<Type::MatrixTransform>, std::string) {}
    static auto create(tag<Type::Cube>) {}
    static auto create(tag<Type::Sphere>) {}
};

int main() {
    Factory::create<Type::MatrixTransform>();
    Factory::create<Type::MatrixTransform>("foo");
}

重载、模板和标签调度在这里完成工作。


注意:该示例需要 C++14,但需要使用正确的返回类型而不是 auto,它也适用于 C++11。

【讨论】:

  • 想先试试地图。发现有趣的变量参数模板你正在使用,一定会试一试。非常感谢您的帮助。
  • @LastBlow 地图具有固定类型。您想使用不同的函数定义作为值。这是不可能的,除非你最终使用函子。在这种情况下,您只是在基于重载的解决方案之上添加了一个无用的层。
【解决方案2】:

刚刚想到了 2 个可能的解决方案。

我可以创建 3 个映射而不是一个:一个用于没有参数的函数,第二个用于具有一个参数的函数,第三个用于具有 2 个参数的函数。这样,我将有 3 个映射,每个映射都有具有相同签名的函数的唯一映射条目!

一个更简单的解决方案是保留初始映射并继续使用通用构造函数创建对象,然后使用 setter 设置它们的名称和矩阵变换参数。

嘿,他们真的说你必须提出问题才能找到答案!梦想在代码中。

【讨论】:

  • 因推荐可能运行良好的无聊的低技术解决方案而被投票赞成 :)
  • @Christian Hackl 哈,哈,哈,谢谢,你让我笑了。嘿,任何人都想用高科技解决方案来激发更多的兴奋,比如一些具有可变数量参数的模板函数? ;-)))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多