给定以下问题:
class Instrument {
};
class Guitar : public Instrument {
public:
void doGuitar() const;
};
class Piano : public Instrument {
public:
void doPiano() const;
};
我得到了指向 Instrument
的指针列表
list<shared_ptr<Instrument>> instruments;
在其中我通过(例如)添加乐器
Guitar myGuitar;
instruments.push_back(make_shared<Guitar>(myGuitar));
现在,我想遍历列表 instruments
并调用 doPiano()
当且仅当当前乐器是钢琴和 doGuitar()
如果它是一把吉他。这两个函数差别很大,因此不能在 Instrument
类中进行抽象。
问题是 C++ 无法通过运行时识别 Instrument
的类型,不是吗(由于单次分派(dispatch))?我怎样才能实现它根据迭代器指向的当前类型调用钢琴或吉他功能。
如果我能实现某事,我会很高兴。像这样伪代码工作:
list<shared_ptr<Instrument>>::const_iterator it;
if ("current type == Guitar")
(*it)->doGuitar();
else if ("current type == Piano")
(*it)->doPiano();
结果
实际上,我的方法遇到了几个问题。我使用这篇文章做了很多重构:How does one downcast a std::shared_ptr? .感谢大家的帮助:)
最佳答案
可能可以改进设计以消除此问题,但在现有设计中,您可以添加一个虚拟成员函数 Instrument::play_it
将 Player
作为多态参数。在Player
中有两个函数play_guitar
(以吉他为参数)和play_piano
(以钢琴为参数)。在吉他类中重写 play_it
以调用 Player::play_guitar
并将 self 作为参数。在 piano 类中重写 play_it
以调用 Player::play_piano
并将 self 作为参数。看起来没有石膏。
这不完全是多重分派(dispatch),它被称为访问者模式。然而,最好不要过分关注这一点,以免您开始为事物命名 visitor
或此类非描述性的愚蠢行为。
关于C++ 多重分派(dispatch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41097609/