Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/381.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+中的方法+;_C++_Visitor_Double Dispatch - Fatal编程技术网

C++ 访客和双重派遣,无需覆盖“;接受;c+中的方法+;

C++ 访客和双重派遣,无需覆盖“;接受;c+中的方法+;,c++,visitor,double-dispatch,C++,Visitor,Double Dispatch,好的:我的问题是:我有一个基本的composit类,它接受访问者,然后在其节点上迭代。工作起来很有魅力。 但是,我必须使用从这个composit派生的方法,并认识到我必须重写派生类中的“accept()”方法,以获得正确的双重分派(我不理解) 这带来了两个缺陷:第一,我必须打破基础的隐藏结构,第二,我必须复制代码。为了澄清,这里是我的伪代码: struct Visitor { void visit( BaseComposit*) { throw( "not expected");

好的:我的问题是:我有一个基本的composit类,它接受访问者,然后在其节点上迭代。工作起来很有魅力。 但是,我必须使用从这个composit派生的方法,并认识到我必须重写派生类中的“accept()”方法,以获得正确的双重分派(我不理解)

这带来了两个缺陷:第一,我必须打破基础的隐藏结构,第二,我必须复制代码。为了澄清,这里是我的伪代码:

struct Visitor
{
    void visit( BaseComposit*)    { throw( "not expected"); };
    void visit( DerivedComposit*) { throw( "ok"); };
};

class BaseComposit 
{
private:  

    std::vector< BaseComposit*> nodes;

public:

    virtual void accept( Visitor* v)
    {
        v->visit( this);

        for( int i = 0; i < nodes.size(); i++)
            nodes[ i]->accept( v);
    }
};

class DerivedComposit : public BaseComposit
{
public:
};
struct访问者
{
无效访问(BaseComposit*){throw(“不期望”);};
无效访问(DerivedComposit*){throw(“ok”);};
};
类BaseComposit
{
私人:
std::vector节点;
公众:
虚拟无效接受(访客*v)
{
v->参观(本次);
对于(int i=0;i接受(v);
}
};
类DerivedComposit:公共基复合
{
公众:
};
在这方面有什么好办法吗? 谢谢大家!

编辑:在“accept()”中添加了“virtual”以使其更精确

在这方面有什么好办法吗

不是真的。这就是为什么访客模式有点痛苦。尽管您可以借助模板稍微减少重复:

class BaseComposit 
{
private:  

    std::vector<BaseComposit*> nodes;

protected:

    template<class T>
    void accept_impl( Visitor* v, T* this_ )
    {
        v->visit( this_ );

        for(int i = 0; i < nodes.size(); i++)
            nodes[i]->accept(v);
    }

public:

    virtual void accept( Visitor* v ) { accept_impl( v, this ); }
};
但是您仍然需要在每个派生类中使用它来显示定义

class DerivedComposit : public BaseComposit
{
public:
    INJECT_ACCEPT();
};

。因此,我想有人可能会说,上面的代码看起来“很自然”。

如果您想强制始终执行某些代码,请使用非虚拟接口(NVI)模式:

classbasecomposit
{
私人:
std::向量节点;
虚拟无效调用_visit(Visitor*v){v->visit(this);}
公众:
无效接受(访客*v)
{
拜访(五);
对于(int i=0;i接受(v);
}
};
类DerivedComposit:公共基复合
{
void call_visit(Visitor*v)覆盖{v->visit(this);}
公众:
};

吹毛求疵,但左大括号后的空格与右大括号前的空格不匹配有点令人讨厌。为什么不在基类中将accept声明为virtual,并在派生类中实现重写?访问者模式就是这样。你可能想尝试一下“非循环访问者”的东西。我的
(要点)(就是)(这个)
这种风格可能会在代码评审中引起很多讨论。相信我,一个空格可以和多个空格一样突出。我可以得到
(这个)
(这个)
,但我担心
(这个)
总是会成为我在代码评审中的一个问题。但是YMMV:)但是“this”始终是一个BaseComposit*?@Oliv-使其虚拟化是另一回事:)谢谢-我将使用模板,是的,当然它必须是虚拟的。这就是我为什么写“伪代码”;-)再次感谢您的快速响应!伟大的社区@user9066185-好吧,我添加了另一个小道消息。它避免了更多的重复,但有点可疑。模板方法在这里有什么用?这仅仅是为了让代码更加C++y吗?@affenärschle:所以,摆脱
override
@Jarod42:jup-works。但是我不明白为什么编译器可以选择正确的vtable条目Base/Derived而不是visitor中的vtable条目。。。不管怎样,塞巴斯蒂安,好办法。好的-访客没有vtabel。。。我真丢脸
class DerivedComposit : public BaseComposit
{
public:
    INJECT_ACCEPT();
};
class BaseComposit 
{
private:  
    std::vector<BaseComposit*> nodes;

    virtual void call_visit(Visitor* v) { v->visit(this); }

public:

    void accept(Visitor* v)
    {
        call_visit(v);

        for(int i = 0; i < nodes.size(); i++)
            nodes[i]->accept(v);
    }
};

class DerivedComposit : public BaseComposit
{
    void call_visit(Visitor* v) override { v->visit(this); }
public:
};