[英]C++: Selecting a Derived Class through a Base Using Overloading instead of Dynamic Cast
As an example to my question, imagine a base class like so: 作为我的问题的一个示例,想象一个像这样的基类:
struct Agent {
void compete(const Agent& competitor) const = 0;
};
Associated with a derived like this: 与这样的派生关联:
struct RockAgent;
struct PaperAgent;
struct ScissorsAgent: public Agent {
void compete(const Agent& competitor) const override {
if(dynamic_cast<const RockAgent*>(&competitor))
std::cout << "I have lost" << std::endl;
else if(dynamic_cast<const PaperAgent*>(&competitor))
std::cout << "I have won!" << std::endl;
//etc....
}
};
And compare it to this base: 并将其与此基础:
struct PaperAgent;
struct RockAgent;
struct ScissorsAgent;
struct Agent {
void compete(const PaperAgent& competitor) const = 0;
void compete(const RockAgent& competitor) const = 0;
void compete(const ScissorsAgent& competitor) const = 0;
};
and this derived: 并由此得出:
//forward needed classes.....
struct PaperAgent: public Agent {
void compete(const PaperAgent& competitor) const override {
std::cout << "I have won!" << std::endl;
}
//etc......
};
If I try to use these two methods by passing to the compete() function an Agent polymorphic instance (reference in this case) only the first one compiles. 如果我试图通过传递给validate()函数来使用这两种方法,那么Agent多态实例(在这种情况下为引用)只会编译第一个。 In the second case, the compiler complains that there is no such function as compete(const Agent&).
在第二种情况下,编译器会抱怨说没有诸如compare(const Agent&)这样的功能。 I understand why this does not work, but is there any alternative out there that does not require dynamic_cast and is closer to the second case showed above in terms of design?
我知道为什么这行不通,但是有没有其他替代方法不需要dynamic_cast,并且在设计方面更接近上面显示的第二种情况? Maybe a design pattern that I'm not aware of, or that I've never imagined could be used to emulate this?
也许我不知道的设计模式,或者我从未想过的设计模式可以用来模仿?
Change Agent
: 变更
Agent
:
struct Agent {
virtual void competeWith(const Agent& competitor) const = 0;
void compete(const Agent& competitor) const { compeditor.competeWith(*this); }
virtual void compete(const PaperAgent& competitor) const = 0;
virtual void compete(const RockAgent& competitor) const = 0;
virtual void compete(const ScissorsAgent& competitor) const = 0;
};
In PaperAgent: 在PaperAgent中:
struct PaperAgent: public Agent {
void competeWith(const Agent& competitor) const override final {
compeditor.compete(*this);
}
void compete(const PaperAgent& competitor) const final override;
void compete(const RockAgent& competitor) const final override;
void compete(const ScissorsAgent& competitor) const final override;
}; };
this may be helped with the crtp: crtp可以帮助您:
template<class D>
struct AgentImpl: public Agent
void competeWith(const Agent& competitor) const override final {
compeditor.compete(*static_cast<D const*>(this));
}
};
struct PaperAgent: public AgentImpl<PaperAgent>{
void compete(const PaperAgent& competitor) const final override;
void compete(const RockAgent& competitor) const final override;
void compete(const ScissorsAgent& competitor) const final override;
};
to reduce code replication. 减少代码复制。
a1.compete(Agent const& a2)
invokes a2.competeWith(a1)
, which in turn invokes a1.compete(a2)
using the dynamic type of a2
and full overload resolution. a1.compete(Agent const& a2)
调用a2.competeWith(a1)
,而a1.compete(a2)
使用动态类型的a2
和完全重载分辨率来调用a1.compete(a2)
。
This is one of many standard ways to do "double dispatch" -- acting virtually on two arguments at once. 这是执行“双重调度”的许多标准方法之一-几乎同时作用于两个参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.