gpt4 book ai didi

c++ - 模板派生类的访问者模式

转载 作者:行者123 更新时间:2023-11-30 04:17:53 25 4
gpt4 key购买 nike

相关问题:link .

在上述问题的一个答案中,有人建议我使用访问者模式来解决我的类继承结构的一些问题。但是,我不确定是否可以在我的上下文中使用它,因为我的派生类可以是非类型模板。

为了展示问题,我使用了来自以下来源的修改代码:http://sourcemaking.com/design_patterns/visitor/cpp/2 .下面的示例无法编译,因为无法定义虚拟模板方法。但是,我相信,代码演示了我正在努力实现的目标。有没有其他解决方案可以解决这个问题?

// 1. Add an accept(Visitor) method to the "element" hierarchy
class Element
{
public:
virtual void accept(class Visitor &v) = 0;
};

template <unsigned int N>
class This: public Element
{
public:
/*virtual*/void accept(Visitor &v);
string thiss()
{
return "This";
}
};

class That: public Element
{
public:
/*virtual*/void accept(Visitor &v);
string that()
{
return "That";
}
};

// 2. Create a "visitor" base class w/ a visit() method for every "element" type
class Visitor
{
public:
template<unsigned int N>
virtual void visit(This<N> *e) = 0;
virtual void visit(That *e) = 0;

};

template<unsigned int N>
/*virtual*/void This<N>::accept(Visitor &v)
{
v.visit(this);
}

/*virtual*/void That::accept(Visitor &v)
{
v.visit(this);
}

// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor: public Visitor
{
/*virtual*/void visit(This *e)
{
cout << "do Up on " + e->thiss() << '\n';
}
/*virtual*/void visit(That *e)
{
cout << "do Up on " + e->that() << '\n';
}

};

class DownVisitor: public Visitor
{
/*virtual*/void visit(This *e)
{
cout << "do Down on " + e->thiss() << '\n';
}
/*virtual*/void visit(That *e)
{
cout << "do Down on " + e->that() << '\n';
}

};

int main()
{

Element *list[] =
{
new This<3>(), new That()
};
UpVisitor up; // 4. Client creates
DownVisitor down; // "visitor" objects
for (int i = 0; i < 2; i++) list[i]->accept(up);
for (int i = 0; i < 2; i++) list[i]->accept(down);
}

最佳答案

问题是您的 Visitor 类与派生自 Element 的类紧密耦合。当你扩展你的设计时,这将比现在更阻碍你。您可以通过提供定义可访问对象的所有要求的“目标”类来减少/消除正确的耦合。由于派生类的名称是一个公共(public)属性,因此您也可以将存储和访问权限放入目标类中。

// 1. Define out visitor and destination interfaces
struct Destination
{
Destination(const std::string& name) : name_(name) {}
virtual std::string ident() const { return name_; }

const std::string name_;
};

struct Visitor
{
virtual void visit(Destination *e) = 0;
};

这使访问者的要求与 Element 类分开,这似乎是您的意图。然后您的 ThisThat 类继承自 Destination 并提供必要的实现。

// 2. Define our element and it's derived classes
class Element
{
public:
virtual void accept(class Visitor &v) = 0;
};

template <unsigned int N>
class This: public Element, public Destination
{
public:
This() : Destination("This") {}
virtual void accept(Visitor &v)
{
v.visit(this);
}
};

class That: public Element, public Destination
{
public:
That() : Destination("That") {}
virtual void accept(Visitor &v)
{
v.visit(this);
}
};

现在你的上行和下行访问者被简化成类似下面的东西

// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor: public Visitor
{
void visit(Destination *e) {
cout << "do Up on " + e->ident() << '\n';
}
};

class DownVisitor: public Visitor
{
void visit(Destination *e) {
cout << "do Down on " + e->ident() << '\n';
}
};

虽然我没有在上面的解决方案中更改它,但我建议更改 visit 以获取引用而不是指针。由于 C++ 没有空引用的概念,这表明 Destination必需的,而指针可以被视为可选

关于c++ - 模板派生类的访问者模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16780859/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com