我有以下代码:
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;
}我得到了以下错误:
||=== 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++方法“不起作用:
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表达式/闭包):
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;
}问题是,场景构造函数的第二个参数接受一个函数指针:
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表达式(它不是函数),因此我得到以下错误:
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++向导)。
发布于 2015-06-16 07:33:43
只需将图像放在visual_plot函数中并使其保持静态:
void visual_plot()
{
static Image img("sample.png");
x.draw(); // Problem.
}这将在第一次调用img时初始化visual_plot,而且只有在那时。这将解决性能问题和“必须在app.run()之后初始化”问题。
发布于 2015-06-16 08:24:59
这是一个设计问题。为了完成您想要完成的任务,您需要两部分信息:要执行的代码和要针对其执行的数据。
lambda不是魔法,它只是将这两者封装在一个对象中,这就是为什么它不能很好地衰减到单个函数指针。具有捕获功能的lambda是函数对象的语法糖:
int x, y;
float f;
// ...
auto l = [x, &y, f] () { return static_cast<int>((x + y) * f); };
int r = l();是为了让你免于写作
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()‘的指针,以及一个指向调用它的实例的指针。
int r = Capture::operator=(&c); // pseudo使用静态或全局变量,您可以在编译时使数据的地址为人所知,从而允许您只需要一个函数指针。
但是,您的设计是一个strcpy,它只需要一个参数,或者一个不需要任何参数的打印函数:您如何知道复制或打印什么?
更好的设计是让您将函数对象传递给绘图函数,查看STL谓词是如何工作的,这将允许函数指针和lambda,或者使用虚拟函数和子类。
struct Scene { virtual void plot(); };
struct MyScene : public Scene {
Image x;
MyScene() : x("image") {}
void plot() override { x.draw(); }
};这种方法的缺陷是"切片",如果允许派生类型,则需要通过引用而不是通过值传递Scene:
void foo(Scene& s) {
s.plot();
}
foo(MyScene(...)); // not going to go wellhttps://stackoverflow.com/questions/30858722
复制相似问题