Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.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++ 内部类实现接口的Lambda_C++_C++11_Interface_Lambda_Inner Classes - Fatal编程技术网

C++ 内部类实现接口的Lambda

C++ 内部类实现接口的Lambda,c++,c++11,interface,lambda,inner-classes,C++,C++11,Interface,Lambda,Inner Classes,我对lambdas还不是很有经验,但我开始非常喜欢它们,并在有意义的地方使用它们,在我觉得它们是我的方向的地方使用它们 无论如何,我有一个类Tree,它有一个Tree::Visitor类,有一个名为visit(/*args*/)的虚拟回调函数。该访问者类在所有节点上执行递归遍历。通过这个回调,我可以从每个节点收集数据(或者更好地,我可以提取树的路径(这基本上就是我使用这个函数所做的) 因此,我使用一个lambda,并在内部使用一个类来实现visit回调函数,它是从Tree::Visitor派生的

我对lambdas还不是很有经验,但我开始非常喜欢它们,并在有意义的地方使用它们,在我觉得它们是我的方向的地方使用它们

无论如何,我有一个类
Tree
,它有一个
Tree::Visitor
类,有一个名为
visit(/*args*/)
的虚拟回调函数。该访问者类在所有节点上执行递归遍历。通过这个回调,我可以从每个节点收集数据(或者更好地,我可以提取树的路径(这基本上就是我使用这个函数所做的)

因此,我使用一个lambda,并在内部使用一个类来实现
visit
回调函数,它是从
Tree::Visitor
派生的

// Tree class, a rough view how it looks
class Tree {

    // ...

    // Visitor class for recursive walking the tree
    class Visitor {
       // 
       void count(/* ... */) {
           // in here the implemented visit(/*args*/) fct is called
       }

       // ...
       void triggerVisit() { 
           // ...
           count(/* ... */);
           // ...
       }

       // visitor callback
       virtual void visit(/* args */) = 0;
    };
};

class A {
    Tree tree;
    PriorityQueue que;

    A() : tree(), que(maxEntries) {}

    // first build the tree ...
    void buildTheTree() {
        tree.buildTree();               
    }

    // walk the tree
    void visitTheTree() {

       std::shared_ptr<Tree::Visitor>(
          [&]()->Tree::Visitor * {

             // this class implements visit(/*args*/)
             class MyVisitor : public Tree::Visitor {
                 A& parent; // pointer to A

                 Myvisitor(A& p) 
                 : Tree::Visitor(p.tree), parent(p) {}      

                 // implementation
                 virtual void visit( /* args */ ) {

                     // ... get somedata 

                     if (/* condition true */) {
                         parent.que.push(somedata);
                     }
                 }  
             };

             return new MyVisitor(*this);

          }()
       )->triggerVisit();

       // get the collected data from que
       while(que.size() > 0) {
          // ...
       }
    }
};
//树类,粗略查看它的外观
类树{
// ...
//用于递归遍历树的访问者类
班级访客{
// 
无效计数(/*…*/){
//在这里,调用实现的访问(/*args*/)fct
}
// ...
void triggerVisite(){
// ...
计数(/*…*/);
// ...
}
//访客回访
虚拟无效访问(/*args*/)=0;
};
};
甲级{
树木;
优先权;
A():tree(),que(maxEntries){}
//首先建造这棵树。。。
void buildTheTree(){
buildTree();
}
//在树上散步
void visitTheTree(){
std::共享的ptr(
[&]()->树::访问者*{
//此类实现了visit(/*args*/)
类MyVisitor:public树::Visitor{
A&parent;//指向
我的访客(A&p)
:Tree::访问者(p.Tree),父(p){}
//实施
虚拟无效访问(/*args*/){
//…获取一些数据
如果(/*条件为真*/){
parent.que.push(somedata);
}
}  
};
返回新的MyVisitor(*此项);
}()
)->TriggerVisite();
//从que获取收集的数据
而(que.size()>0){
// ...
}
}
};
基本上这就是我所拥有的,而且它工作起来没有问题

我有一个优先级队列
que
,我用它来存储
somedata
,这是树中得分最高的
n
节点。此时
que
被定义为类
a
的一个成员,我不喜欢它,因为我只需要在visittree成员中收集数据,所以它可能是本地va易变的 所以我的问题更多的是设计/风格的问题,我觉得我错过了c++11标准的某些东西(也许)

我试图在
visitTheTree()
中定义
que
,并将其与
MyVisitor
的构造函数一起传递。不知何故,这工作不正常,至少我没有得到预期的正确/完整的结果。当我将优先级队列变量定义为的成员时(现在是这样)使用MyVistor中的父指针访问它,我得到了正确的结果,一切都很好

有没有什么好方法可以在VisitTheTree()中本地定义
que
,而不是在类A中将其定义为成员?我知道我必须通过构造函数传递它,因为我无法访问MyVistor之外的变量(就像这样)

顺便说一句,我发现这个问题与我的问题很接近。有趣的是约翰的答案


欢迎提供任何提示或想法。感谢您的想法和帮助!

Andreas,我真的很想帮助您,但我无法找到使用您的设计来实现这一点的方法。我在使用boost graph library时遇到过类似情况,我做了以下几点(希望对您有所帮助):

  • Visitor有一个
    std::function
    成员,用于对您访问的每个节点执行操作。我还将此函数作为Visitor构造函数的参数
  • 每次需要访问某些节点时,都会通过访问者的一个新实例传递一个新的lambda函数作为参数
我想提供一些例子

class Tree {
    ...
    typedef std::function<void (/*node and args*/)> visit_fn;

    class Visitor {
        visit_fn& visitor;

        public:
            Visitor( visit_fn f ) : visitor( f ) {}
        ...
    };
};

class A {

    ...

    void visit_tree() {
        que.clear(); // could also be a local queue object

        Visitor vis([&](/*args*/) {
            que.push( some_data ); /*I have que because of & in my lambda*/
        });

        vis.triggerVisit();

        // Her I can use my queue member
    }

};
类树{
...
typedef标准::功能访问\u fn;
班级访客{
参观(fn)及访客;;
公众:
访客(访客):访客(访客)
...
};
};
甲级{
...
无效访问树(){
que.clear();//也可以是本地队列对象
Visitor vis([&](/*args*/){
que.push(一些_数据);/*我之所以有que是因为我的lambda中有*/
});
vis.triggerVisit();
//我可以使用我的队列成员
}
};
现在,如果您有一种访问元素的常用方法,您甚至可以向访问者传递一个函子,从而提供更好的代码重用


我真的认为您设计中的lambda没有使用
[&]
绑定,从这个意义上讲,它可能是一个常见的功能,我认为它会更干净、可重用和高效。

从头开始是一个选项吗?我有一个印象,您概述的许多代码都是不必要的——我甚至可以说,有趣的部分实际上是您遗漏的。您熟悉吗带折叠的r(在C++中通常以
std::acculate
为幌子)?这可能是在查看数据时聚合结果的一种适当方法。其他一些方法可能是适当的,但这取决于您如何查看数据以及想要得到什么结果。这些是缺少的有趣的部分。@LucDanton我从未使用过std::accumulate,我想我不能在这种情况下使用它。可能如果我有一个容器的话(例如,物体的矢量)我可以这样做。我对整体设计很满意,也不想重写树,因为它工作得很好。我只是在想上面与访问者收集数据的那部分,也许没有其他方法,就像现在一样,我只是好奇