【问题标题】:Which base class is calling derived overridden method? [duplicate]哪个基类调用派生的重写方法? [复制]
【发布时间】:2018-01-18 16:38:48
【问题描述】:

我有以下使用多重继承的代码。目的是在派生类中将两个接口合二为一:

struct InterfaceA
{
    virtual void register_stuff();
    virtual void on_state_changed( const State state ) = 0;
};

struct InterfaceB
{
    virtual void register_stuff();
    virtual void on_state_changed( const State state ) = 0;
};

struct Derived : InterfaceA, InterfaceB
{
    void register_stuff() override
    {
        InterfaceA::register_stuff();
        InterfaceB::register_stuff();
    }

    void on_state_changed( const State state ) override
    {
        // how can I know who is responding?
    }
};

注册接口将导致对on_state_changed 的异步调用。是否可以辨别是哪个接口调用它?

【问题讨论】:

  • 如果你需要这些信息,为什么不添加一个参数告诉你你需要什么?
  • 或者干脆避免使用多重继承。
  • 我认为article 在陷阱副标题下有一些关于此的信息。
  • @BoPersson 我无法修改接口:那些来自库
  • @Ron 答案是“没有办法知道”吗?

标签: c++ overriding multiple-inheritance


【解决方案1】:

或者,可以直接在 Derived 的代码中为处理程序提供单独的实现:

    struct Derived : InterfaceA, InterfaceB
     {
        void register_stuff() override
        {
            InterfaceA::register_stuff();
            InterfaceB::register_stuff();
        }

        void InterfaceA::on_state_changed( const State state ) override
        {
            // responding A
        }

        void InterfaceB::on_state_changed( const State state ) override
        {
            // responding B        
        }
  };

编辑:不幸的是,此解决方案是非标准的,仅受 Visual C++ 编译器支持。

【讨论】:

  • 这不是为我编译的。您使用的是哪个编译器 + 版本?
  • 是VS 2010,应该是经典的C++。你遇到了什么错误?
  • 错误:无法在“Derived”中定义成员函数“InterfaceA::on_state_changed” void InterfaceA::on_state_changed(const State state) override { } ^
  • 这有点酷。有人在 C++ 委员会中推动它吗?
【解决方案2】:

我也在考虑使用模板来消除歧义,但我相信 @StoryTeller 的答案更优雅。

struct InterfaceA
{
    virtual void register_stuff();  // calls on_state_changed<InterfaceA>()

    template <typename Interface>
    virtual void on_state_changed( const State state ) = 0;
};

struct InterfaceB
{
    virtual void register_stuff();  // calls on_state_changed<InterfaceB>()

    template <typename Interface>
    virtual void on_state_changed( const State state ) = 0;
};

struct Derived : InterfaceA, InterfaceB
{
    void register_stuff() override
    {
        InterfaceA::register_stuff();
        InterfaceB::register_stuff();
    }

    template <typename Interface>
    void on_state_changed( const State state ) override
    {
        // how can I know who is responding?
        // : "Interface" is responding
    }
};

【讨论】:

    【解决方案3】:

    您必须在中间添加一个图层以消除歧义。这是一个可以即时创建这些的小实用程序:

    template<class Inteface>
    struct disambiguate : Interface {
      void on_state_changed( const State state ) override final {
        on_state_changed(state, this);
      }
      virtual void on_state_changed( const State &state, disambiguate* ) = 0;
    };
    

    就是这样。然后是根据这个实用程序定义你的类的问题:

    struct Derived : disambiguate<InterfaceA>, disambiguate<InterfaceB>
    {
        void register_stuff() override
        {
            InterfaceA::register_stuff();
            InterfaceB::register_stuff();
        }
    
        void on_state_changed( const State &state, disambiguate<InterfaceA>* ) override
        {
            // Called for A
        }
    
        void on_state_changed( const State &state, disambiguate<InterfaceB>* ) override
        {
            // Called for B
        }
    };
    

    我使用了另一个参数和重载来使这个模板化,但是技术本身也可以通过写出类并使用新名称调用虚函数来完成。关键是使原始虚拟调用(通过接口指针)到达一个调用消歧函数的简短 thunk。

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多