使构造函数适应工厂要求

问题描述 投票:0回答:1

我是从无法控制的基类派生一个类。该类将由我传入的工厂函数指针创建(在我也不控制的部分代码中)。

在派生类中,我需要向工厂函数传递一个附加的构造函数参数。

我的第一个选项是尝试通过lambda来适应工厂功能,但这无法捕获其他参数。其他答案解释了为什么这行不通。接下来,我尝试用std::function来补充该问题,其他答案使我相信它可以起作用,但是我无法找出正确的语法,并且发现这些示例令人难以理解(并且不确定我是否真的理解那个例子)甚至还在做)。

我在这里做错了什么?有没有更好的方法来解决这个问题?

演示代码:

#include <functional>
#include <string>

// I have no control over this
struct Base {
    Base(int i) {}
};

void UseObject(Base *(*factory)(int i)) {
    Base *instance = factory(5);
    // Save created instance
}

// I control the rest
struct Derived : public Base {
    Derived(const char *s, int i) : Base(i) { /* Store s for later use */ }

    static Base *Factory(const char *s, int i) { return new Derived(s, i); }
};

void AddObject(const char *name)
{
    // First stab
    // UseObject([name] (int i) { return Derived::Factory(name, i); });

    // Second stab
    std::function<Base *(int i)> foo { [name] (int i) { return Derived::Factory(name, i); } };
    UseObject(foo);
}

int main(int ac, char **av)
{
    AddObject("some_name");
    AddObject("another_name");
    return 0;
}

我从g ++(7.4.0)得到的错误是:

tfunc.cpp: In function ‘void AddObject(const char*)’:
tfunc.cpp:28:18: error: cannot convert ‘std::function<Base*(int)>’ to ‘Base* (*)(int)’ for argument ‘1’ to ‘void UseObject(Base* (*)(int))’
 UseObject(foo);
c++
1个回答
1
投票

UseObject不允许不捕获lambda或std::function或常规类函子。它接受的唯一可调用对象是函数指针(无法捕获的lambda可以转换为)。

所以您可以这样做:

UseObject([](int i) { return Derived::Factory("some_name", i); });

但不是

auto name = "some_name";
UseObject([name] (int i) { return Derived::Factory(name, i); });

可能的(有限的)解决方法是使用全局变量来存储状态。 (因此不能同时使用。)>

void AddObject(const char *name)
{
    // global usage as UseObject only accepts pointer function
    static const char* instance = nullptr;

    instance = name;
    UseObject(+[](int i) { return Derived::Factory(instance, i); });
}
© www.soinside.com 2019 - 2024. All rights reserved.