我有以下类(class):

class A {
};

class B : public A {
};

class P     {
private:
 std::list<A*> l
protected:
 virtual void DoIt(A* a) = 0;
public:
 void WorkerThread() { for (it=l.begin(); it!=l.end(); it++) DoIt(*it); }
};

class Q : public P
{
protected:
 void DoIt(A* a) { print("false"); }
 void DoIt(B* b) { print("true"); }
};

不幸的是,DoIt(B * b)永远不会被调用。
即使将B对象添加到列表中,也会始终调用DoIt(A * a)。

我该怎么做才能使DoIt(B * b)被调用?
如果B不知道Q,有可能实现这一目标吗?
如果没有动态强制转换,是否可以实现此目标?

谢谢

最佳答案

好吧,没有人真的能直接回答您的问题(好吧,经过反复尝试),所以我会的。实际上,这里的其他“答案”实际上更有助于解决问题。

问题是void DoIt(B *)不会覆盖虚拟函数DoIt(A *)。这是一个超载。有很大的不同。

当您说在传递B *时未调用DoIt(B *)时,我必须假设您正在通过指向上级较高层次的指针持有Q的引用或指针。在这些情况下,静态名称解析只能找到DoIt(A *),并且由于B *是-A *,因此将其向上转换,这就是被调用的版本。由于它是虚拟的,因此称为Q的替代。

如果您有一个指向Q的指针作为指向Q的指针,并且使用B *调用了DoIt,则应该调用DoIt(B *)函数。在这一点上,不需要并且不使用双重调度。

当您有两种抽象类型,并且一个函数必须基于两种抽象的具体类型而表现不同时,您需要进行双重调度。这是您尝试以比静态命名提供的更高级别调用Q上的B的DoIt时要执行的操作。有太多方法可以满足您的不同需求,从而能够针对您的情况提出一种解决方案,而不是真正地知道您要解决的问题。实际上,您甚至可能不需要它!对您来说,更好的方法可能是将DoIt(B *)作为虚拟函数实现在更高层体系结构的顶部。

我建议您阅读Andre Alexandrescu的书《 Modern C++ Design》,并仔细阅读。他解释了一个非常酷的访客实现以及可扩展的多重调度机制。但是不要止步于此,还有其他很棒的实现可以不同地回答这个问题。

祝好运。

关于c++ - 如何为一个虚拟功能提供多个替代,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4463437/

10-13 05:55