首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在没有C++11中的lambda表达式的情况下模拟嵌套函数?

如何在没有C++11中的lambda表达式的情况下模拟嵌套函数?
EN

Stack Overflow用户
提问于 2015-06-16 04:19:59
回答 2查看 1.2K关注 0票数 2

我有以下代码:

代码语言:javascript
复制
int main(int argc, char **argv)
{
    App app(800, 600);
    app.add_event_scene(Scene("Event Plot", event_plot));

    Image x("sample.png");
    struct foo { static void visual_plot() { x.draw(); } }; // Error.

    app.add_visual_scene(Scene("Visual Plot", foo::visual_plot));
    app.run();
    return 0;
}

我得到了以下错误:

代码语言:javascript
复制
||=== Build: Debug in Joy-Plus-Plus (compiler: GNU GCC Compiler) ===|
G:\Development\Game-Development\CB\Joy-Plus-Plus\main.cpp|54|error: use of local variable with automatic storage from containing function|
G:\Development\Game-Development\CB\Joy-Plus-Plus\main.cpp|53|error:   'Image x' declared here|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

我在写多媒体/游戏引擎用于快板5库,我已经将主循环的绘图部分(以及事件部分)抽象为带有情节(函数)的“场景”对象。每个过程都被传递给App,这样它就可以在主循环中“运行”。问题是,"C++方法“不起作用:

代码语言:javascript
复制
Image x("sample.png");

void visual_plot()
{
    x.draw(); // Problem.
}

int main(int argc, char **argv)
{
    App app(800, 600);
    app.add_event_scene(Scene("Event Plot", event_plot));
    app.add_visual_scene(Scene("Visual Plot", visual_plot));
    app.run();
    return 0;
}

虽然代码运行,但会发生这样的情况:

如果我将x放入visual_plot中,图像通常会被加载:

但是现在我有了一个巨大的性能问题,因为在每个主循环中都会创建一个新的Image对象(而且不需要很长时间就会冻结整个程序)。

当我将其置于函数的范围之外时,不会发现该图像,因为必须是在应用程序初始化后出现的,但是由于场景中有一个typedef函数指针,将该函数作为参数,所以还必须给它一个空函数。问题是我无法在C++中创建本地/嵌套函数(在应用程序初始化之后)。因此,为了避免这个问题,我尝试了显而易见的(Lambda表达式/闭包):

代码语言:javascript
复制
int main(int argc, char **argv)
{
    App app(800, 600);
    app.add_event_scene(Scene("Event Plot", event_plot));
    Image x("sample.png");
    app.add_visual_scene(Scene("Visual Plot", [&x]()->void{x.draw();}));
    app.run();
    return 0;
}

问题是,场景构造函数的第二个参数接受一个函数指针:

代码语言:javascript
复制
typedef void(*plot)();
typedef map<string, plot> act;

class Scene
{
private:
    string name;
    plot p;
public:
    Scene(string name, plot p);
    ~Scene() {};
    string get_name();
    plot get_plot();
    void set_name(string value);
    void set_plot(plot value);
};

由于函数不能作为参数传递,并被转换为指针,因此同样也适用于lambda表达式(它不是函数),因此我得到以下错误:

代码语言:javascript
复制
G:\Development\Game-Development\CB\Joy-Plus-Plus\main.cpp|52|error: no matching function for call to 'Scene::Scene(const char [12], main(int, char**)::__lambda0)'|

面对这样的悲剧,如何在C++11中模拟嵌套函数?因为像这样的模拟回答不能工作。

我同意这可能是设计上的问题,但我几乎不这么认为。对我来说,C++只是不希望我以任何方式将这个血腥的函数作为参数传递(所以,我请求您帮助long C++向导)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-16 07:33:43

只需将图像放在visual_plot函数中并使其保持静态:

代码语言:javascript
复制
void visual_plot()
{
    static Image img("sample.png");
    x.draw(); // Problem.
}

这将在第一次调用img时初始化visual_plot,而且只有在那时。这将解决性能问题和“必须在app.run()之后初始化”问题。

票数 4
EN

Stack Overflow用户

发布于 2015-06-16 08:24:59

这是一个设计问题。为了完成您想要完成的任务,您需要两部分信息:要执行的代码和要针对其执行的数据。

lambda不是魔法,它只是将这两者封装在一个对象中,这就是为什么它不能很好地衰减到单个函数指针。具有捕获功能的lambda是函数对象的语法糖:

代码语言:javascript
复制
int x, y;
float f;

// ...

auto l = [x, &y, f] () { return static_cast<int>((x + y) * f); };
int r = l();

是为了让你免于写作

代码语言:javascript
复制
struct Values {
    int x;
    int& y;
    float f;

    int operator() () {
        return static_cast<int>((x + y) * f);
    }

    Capture(int x_, int& y_, float f_) : x(x_), y(y_), f(f_) {}
};

//...

Capture c(x, y, f);

int r = c();

这是结束时的成员函数调用,因此涉及两个指针:一个指向成员函数'operator()‘的指针,以及一个指向调用它的实例的指针。

代码语言:javascript
复制
int r = Capture::operator=(&c); // pseudo

使用静态或全局变量,您可以在编译时使数据的地址为人所知,从而允许您只需要一个函数指针。

但是,您的设计是一个strcpy,它只需要一个参数,或者一个不需要任何参数的打印函数:您如何知道复制或打印什么?

更好的设计是让您将函数对象传递给绘图函数,查看STL谓词是如何工作的,这将允许函数指针和lambda,或者使用虚拟函数和子类。

代码语言:javascript
复制
struct Scene { virtual void plot(); };
struct MyScene : public Scene {
    Image x;
    MyScene() : x("image") {}
    void plot() override { x.draw(); }
};

这种方法的缺陷是"切片",如果允许派生类型,则需要通过引用而不是通过值传递Scene

代码语言:javascript
复制
void foo(Scene& s) {
    s.plot();
}

foo(MyScene(...)); // not going to go well
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30858722

复制
相关文章

相似问题

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