【问题标题】:Can I do/mimic things likes this (partial override) in C++?我可以在 C++ 中做/模仿这样的事情(部分覆盖)吗?
【发布时间】:2017-11-21 18:28:03
【问题描述】:

我有两个类AB,都定义了方法m()。尽管这些方法的签名相同,但它们是两种完全不同的方法,具有不同的含义。在课堂C,我想同时更新m()。我不想在C 类中编写一个新的m() 来融合来自AB 的两个m(),我想分别覆盖它们。见以下代码:

class A { public: virtual void m() {cout << "MA" << endl;}};
class B { public: virtual void m() {cout << "MB" << endl;}};
class C : public A, public B { 
   public: virtual void m() update A {cout << "MA2" << endl;}};
   public: virtual void m() update B {cout << "MB2" << endl;}};
}
void func(A* a) { a->m(); }
int main() {
    C* c = new C();
    c->B::m();       //print "MB2"
    func(c);         //print "MA2"
    return 0;
}

我知道 C++ 不支持 update 语法,但是有什么解决方法可以在 C++ 中模拟这种情况吗?

【问题讨论】:

  • this Q&A 看来,您运气不佳。不确定它是否应该作为骗子关闭。
  • c-&gt;B::m();总是调用B::m() 而不进行动态调度。你的例子应该改为B*
  • 是的,你是对的,在 C++ 中,:: 是静态查找。但是,即使我使用“B*”,我想 C++ 中仍然没有办法像我描述的那样定义方法“update”?

标签: c++ multiple-inheritance language-design overriding


【解决方案1】:

多重继承的一个令人讨厌的部分是,在C 中确实只有一个m 覆盖了两者。如果有 2 个或更多定义 m 的类,您需要一个中间人类来消除调用的歧义。幸运的是,您可以使用模板来自动化流程:

template<class C>
class MiddleMan : public C {
  void m() override final { m_impl(this); }
protected:
  virtual void m_impl(MiddleMan*) = 0;
};

现在您只需使用此模板并覆盖它添加的新功能:

class C : public MiddleMan<A>, public MiddleMan<B> { 
   private:
     void m_impl (MiddleMan<A>*) override {cout << "MA2" << endl;}
     void m_impl (MiddleMan<B>*) override {cout << "MA2" << endl;}
};

每个中间人类中m的实现将调用新的重载虚函数。然后定义这些重载。我使用MiddleMan* 作为额外的参数,它有助于重载,但是任何通过值传递成本低且依赖于模板参数的类型都可以消除歧义。

【讨论】:

    【解决方案2】:

    你不能这样做,出于同样的原因,在 C 语言中你不能有两个同名的函数:编译器不知道要调用哪一个! 为了获得您想要的相同效果,我会将您的代码更改为如下所示:

    class A { public: virtual void ma() {cout << "MA" << endl;}};
    class B { public: virtual void mb() {cout << "MB" << endl;}};
    class C : public A, public B { 
       public: virtual void ma() override {cout << "MA2" << endl;} // these are *extra*: };
       public: virtual void mb() override {cout << "MB2" << endl;} // these are *extra*: };
    }
    void func(A* a) { a->ma(); } // the problem here with a->m() would be 
    // that the compiler would not know which m() function to call --
    // you basically want two pointers *crammed* somehow in the same vfptr entry,
    // and the compiler to *automagically* know which one to call,
    // depending on... unspecified conditions!
    int main() {
        C* c = new C();
        c->B::m();       //this will never print "MB2" in your code;
                         //it will always print "MB", no matter what you do!
        c->mb();         //print "MB2"
        func(c);         //print "MA2"
        return 0;
    }
    

    我知道,这可能不是您要寻找的答案,但是您必须更好地描述您的问题。在我看来,正如目前所描述的那样,这解决您的问题的有效方法。

    【讨论】:

      猜你喜欢
      • 2013-06-26
      • 2015-11-17
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 2015-01-23
      • 2016-05-09
      • 2014-03-27
      • 1970-01-01
      相关资源
      最近更新 更多