重载方法实现接口的特例

Ben*_*Ben 9 c++ oop

免责声明:我无法清楚地描述我想要做的事情,所以我希望这个例子比我的解释更清楚!请建议任何重新措辞,以使其更清楚.:)


是否可以覆盖具有比接口所需的更具体版本的函数,以便将该接口中方法的参数的子类分别处理到通用情况?(下面的例子和更好的解释......)如果不能直接完成,是否有一些模式可以用来达到类似的效果?

#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++,但如果您愿意,我也会对一般答案感兴趣(或者如果在其他语言中这更容易/不同).

Arn*_*rtz 2

不,这样是不可能的。虚拟方法分派发生在编译时,即使用处理器指针的静态类型,即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)