免责声明:我无法清楚地描述我想要做的事情,所以我希望这个例子比我的解释更清楚!请建议任何重新措辞,以使其更清楚.:)
是否可以覆盖具有比接口所需的更具体版本的函数,以便将该接口中方法的参数的子类分别处理到通用情况?(下面的例子和更好的解释......)如果不能直接完成,是否有一些模式可以用来达到类似的效果?
#include <iostream>
class BaseNode {};
class DerivedNode : public BaseNode {};
class NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node) = 0;
};
class MyNodeProcessor : public NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node)
{
std::cout << "Processing a node." << std::endl;
}
virtual void processNode(DerivedNode* node)
{
std::cout << "Special processing for a DerivedNode." << std::endl;
}
};
int main()
{
BaseNode* bn = new BaseNode();
DerivedNode* dn = new DerivedNode();
NodeProcessingInterface* processor = new MyNodeProcessor();
// Calls MyNodeProcessor::processNode(BaseNode) as expected.
processor->processNode(bn);
// Calls MyNodeProcessor::processNode(BaseNode).
// I would like this to call MyNodeProcessor::processNode(DerivedNode).
processor->processNode(dn);
delete bn;
delete dn;
delete processor;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望能够实现几个不同的具体NodeProcessor,其中一些将对所有节点进行相同处理(即仅实现界面中显示的内容),其中一些将区分不同类型的节点(如MyNodeProcessor).所以我想第二次调用processNode(dn)使用实施MyNodeProcessor::processNode(DerivedNode)超载(的某些部分/子类)的接口方法.那可能吗?
显然,如果我改为processor类型,MyNodeProcessor*那么这可以按预期工作,但我需要能够交替使用不同的节点处理器.
我也可以通过一个方法processNode(BaseNode)来解决这个问题,该方法在运行时检查其参数的精确类型,并基于此分支.在我的代码中包含此检查似乎不太优雅(特别是当节点类型的数量增长并且我有一个巨大的switch语句时).我觉得这种语言应该能够提供帮助.
我正在使用C++,但如果您愿意,我也会对一般答案感兴趣(或者如果在其他语言中这更容易/不同).
不,这样是不可能的。虚拟方法分派发生在编译时,即使用处理器指针的静态类型,即NodeProcessingInterface。如果该基类型只有一个虚拟函数,则只会调用该一个虚拟函数(或其重写实现)。编译器无法确定可能存在实现更杰出功能的派生 NodeProcessor 类。
因此,您不必使派生类中的方法多样化,而是必须以相反的方式进行:在基类中声明所需的所有不同虚拟函数,并根据需要重写它们:
class NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node) = 0;
//simplify the method definition for complex node hierarchies:
#define PROCESS(_derived_, _base_) \
virtual void processNode(_derived_* node) { \
processNode(static_cast<_base_*>(node)); \
}
PROCESS(DerivedNode, BaseNode)
PROCESS(FurtherDerivedNode, DerivedNode)
PROCESS(AnotherDerivedNode, BaseNode)
#undef PROCESS
};
class BoringNodeProcessor : public NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node) override
{
std::cout << "It's all the same.\n";
}
};
class InterestingNodeProcessor : public NodeProcessingInterface
{
public:
virtual void processNode(BaseNode* node) override
{
std::cout << "A Base.\n";
}
virtual void processNode(DerivedNode* node) override
{
std::cout << "A Derived.\n";
}
};
Run Code Online (Sandbox Code Playgroud)