所以我正在开发一个个人项目(试图在c ++上做得更好),而我正试图让它工作:
我有一个ABC班A. 使用纯虚函数interactWith(A * target);
然后我有两个派生类,B类和C类。
但是,B类必须与C类进行交互,而不是与另一个B类进行交互
我找到了一种在ABC中使用if / else和虚拟getType()的方法,但我很好奇是否有更优雅的方式或者我只是做了一些非常愚蠢的事情,如果我我正在做一些愚蠢的事情(这是非常可能的),我将在哪里开始寻找更好的解决方案(即更合适的设计模式)
请注意:我没有使用boost,我现在宁愿避免使用它,当我真正擅长编程时就开始学习它
欢迎您提供任何帮助。请和谢谢你
我应该注意的事项:B类和C类只能通过A *
显示答案 0 :(得分:2)
您尝试实现的内容称为double dispatch:一个与两个对象相关的虚函数。
有几种方法可以实现它,其中一种更常见的方法是使用visitor pattern。
Scott Meyers在实施双重调度方面有一个很好的章节(他的"More Effective C++"书中的第31项)。他首先讨论了访问者模式,然后使用RTTI进行了非常好的实现。
答案 1 :(得分:2)
您几乎从不想使用类型切换。动态铸造要好一些,但如果可能的话还是要避免。
更好的选择是扭转局面,以便再次使用虚拟调度机制,通常称为“双重调度”或“模拟多方法”。它看起来像这样:
struct B;
struct A {
virtual void interactWith(A* target);
virtual void interactWithB(B* target);
};
struct B : A {
virtual void interactWith(A* target) {
target->interactWithB(this);
}
virtual void interactWithB(B* lhs) {
// B vs. B stuff goes here, but with lhs and this in place of this and target
}
};
struct C : A {
virtual void interactWith(A* target) {
// C vs. anything stuff goes here
}
virtual void interactWithB(B* lhs) {
// B vs. C stuff goes here, again backward
}
};
答案 2 :(得分:0)
使用dynamic_cast
C* cTarget = dynamic_cast<C*>(target);
if(cTarget == NULL)
{
//cTarget is not a C
}
else if(cTarget)
{
//cTarget is a C
}
dynamic_cast做了一些奇特的东西(我不知道它做了什么)来确保强制转换是有效的,如果不是,它会返回NULL。
答案 3 :(得分:0)
理想情况下,在与B进行交互时封装B和C之间需要不同的行为,并将其放入您在target
上调用的另一个虚拟方法 - 然后会有不同的实现适当的方法在B和C中。
如果上述内容过于混乱且过于分散,则表明您选择了错误的抽象作为您的对象。你可能最好不要删除A / B / C类层次结构并将程序划分为不同的层次结构,但是没有更具体的描述你想要做什么,这是不可能的。过早抽象(以及过早优化)是缺乏经验的程序员经常犯的关键错误之一。