Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以在C+;中创建匿名类吗+;捕获外部变量,比如Java?_C++_C++11_Lambda_Anonymous Class - Fatal编程技术网

C++ 我可以在C+;中创建匿名类吗+;捕获外部变量,比如Java?

C++ 我可以在C+;中创建匿名类吗+;捕获外部变量,比如Java?,c++,c++11,lambda,anonymous-class,C++,C++11,Lambda,Anonymous Class,在Java中,当我需要回调函数时,我必须实现一个匿名类。在匿名类中,如果外部变量是final,我可以访问它们 现在我在C++中做同样的事情。我知道C++ LAMBDA工作得更好,但有时我需要传递许多函数,其中匿名类,我只需要传递一个实例。 我尝试了下面的例子。它适用于GCC 4.3.4 class IA { public: virtual int f(int x) = 0; }; int main() { class : public IA { int f(in

在Java中,当我需要回调函数时,我必须实现一个匿名类。在匿名类中,如果外部变量是
final
,我可以访问它们

现在我在C++中做同样的事情。我知道C++ LAMBDA工作得更好,但有时我需要传递许多函数,其中匿名类,我只需要传递一个实例。 我尝试了下面的例子。它适用于GCC 4.3.4

class IA {
public:
  virtual int f(int x) = 0;  
};

int main() {
    class : public IA {
        int f(int x) { return x + 1; }
    } a;
    doFancyWork(&a);
    return 0;
}
有可能像这样捕获外部变量吗

int main() {
    int y = 100; // mark y as final if possible
    class : public IA {
        int f(int x) { return x + y; }
    } a;
    return 0;
}
更新:

第二个示例无法编译。错误就在这里

prog.cpp: In member function ‘virtual int main()::<anonymous class>::f(int)’:
prog.cpp:9: error: use of ‘auto’ variable from containing function
prog.cpp:7: error:   ‘int y’ declared here
prog.cpp: In function ‘int main()’:
prog.cpp:7: warning: unused variable ‘y’
prog.cpp:在成员函数“virtual int main()::f(int)”中:
程序cpp:9:错误:使用包含函数的“自动”变量
prog.cpp:7:错误:此处声明了“int y”
prog.cpp:在函数“int main()”中:
程序cpp:7:警告:未使用的变量“y”
更新:

我刚刚意识到在这样做时还有一些问题:

  • 我无法编写构造函数,因为该类没有名称
  • 初始值设定项列表不允许继承
  • 任何使其编译的更改都会使代码无法读取
<>我想我必须远离匿名类。

一个C++ lambda可以捕获“外部”变量。[编辑:当我第一次阅读这个问题时,我不知怎么地漏掉了他提到的他知道LAMBDAS。不管好坏,C++没有任何其他类似于匿名类的东西。]p> 例如:

#include <iostream>

int main(){ 

    int y = 100;
    auto lambda = [=](int x) { return x + y; };

    std::cout << lambda(2);
}
#包括
int main(){
int y=100;
自动lambda=[=](int x){返回x+y;};

std::cout您可以手动捕获变量(这类似于lambda捕获在幕后所做的操作):

然后您可以这样使用它:

#include <iostream>
...
std::cout << anon(10) << std::endl;
#包括
...
std::cout无法自动捕获这些变量,但您可以使用另一种方法。如果您希望通过引用捕获:

int main() {
    int y = 100; // mark y as final if possible
    class IB : public IA {
    public:
      IB(int& y) : _y(y) {}
      int f(int x) { return x + _y; }
    private:
      int& _y;
    } a (y);
    return 0;
}
如果要按值捕获,只需将
int&
更改为
int

无论如何,您可以考虑使用lambdas <强> >“多回调”对象,如果这是困扰您的单个lambda。您仍然将所有的东西打包在一个对象中,并且捕获将免费完成。

举个例子:

auto callbacks = make_tuple(
    [] (int x) { cout << x << endl; },
    [&] () { cout << y << endl; }, // y is captured by reference
    [=] (int x) { cout << x + y << endl; }, // y is captured by value
    // other lambdas here, if you want...
    );
auto callbacks=make\u tuple(

[](int x){cout如果您的
IA
类实际上只有一个需要重写的虚拟方法(实际的复杂性是其他非虚拟方法),但您不想捕获此方法所需的局部变量,那么这样如何:

int main() {
  int y = 100;
  auto f = [=](int x){return x+y;};
  typedef decltype(f) F;
  struct IB : IA {
    F _f;
    IB(F _f): _f(_f) {}
    int f(int x) { return _f(x); }
  } a(f);
  doFancyWork(&a);
  return 0;
}

不是类的匿名性限制了对外部变量的访问。在这个问题中,y是不可访问的,因为类是在函数中本地定义的

本地定义的类有两个限制。首先,它们只能访问静态的本地变量,但可以访问函数范围内可用的任何其他变量。此外,本地类不能有静态数据成员

至于匿名类,您不能有构造函数或析构函数。所有成员函数都必须在类定义内声明。它不能有静态成员,这包括通常可以在类定义内实例化的const静态整型成员。此外,不允许继承


匿名类是C++中一个晦涩难懂的角落,几乎没有实用价值。LAMBDA函数和其他技术更灵活。但是谁知道,也许在某些情况下它可以帮助代码可读性。< /P>编译和运行吗?第一个例子编译。(用测试)第二个不是。要捕获

y
的值,您需要向匿名类中添加成员
y
(或者lambda自动以这种方式处理“捕获”)4.3.4?为什么要用古老的编译器测试代码?你可以在
IA
中添加一个成员变量
\u y
,并将其设置为
y
的值,然后再将对象作为回调提供。他似乎非常清楚这一点,但不想使用lambda,因为他希望它同时封装许多不同的函数。虽然我不得不从内心深处反对他的做法,并建议只使用lambdas,但你的回答仍然不能真正回答实际问题。@ChristianRau:哎呀,我错过了他提到的了解lambdas的地方。@JerryCoffin我需要将事件处理程序传递给其他人,在那里我可以实现多个事件函数,如onEvent()、onErr()和destroy()。因为可能有太多的事件处理程序,我不想将它们定义为单独的类并分别命名。对于lambda函数,我似乎必须逐个传递它们,或者无论如何都要将它们放入容器类中。至于您的编辑,听起来好像他的
doFancyWork
函数知道要调用哪些函数。因此它不知道只需使用某个模板函数类型的
()
操作符,但需要一个抽象接口,该接口包含他的匿名类实现的一组方法。最后,通常的Java风格回调。尽管仍然有疑问,这种风格是否真的应该转移到另一个Langage,它有自己的惯用语言(也同样灵活)回调方法。恐怕这不会编译…需要一些更改这不会在gcc 4.7.1上编译,gcc 4.7.1是我公司使用的编译器。错误如下,错误:如果继承至关重要,则无法将“{1}”从“”转换为“main():”-如果不是,而且他只是在寻找一个匿名函数对象,那么就确实没有必要避免lambda.+1作为lambda的元组。这是解决当前问题的一个非常简单的方法。@JakeWoods:谢谢。我建议使用它,因为你不必手动处理capturin
int main() {
  int y = 100;
  auto f = [=](int x){return x+y;};
  typedef decltype(f) F;
  struct IB : IA {
    F _f;
    IB(F _f): _f(_f) {}
    int f(int x) { return _f(x); }
  } a(f);
  doFancyWork(&a);
  return 0;
}