【问题标题】:About multiple inheritance and defining virtual function关于多重继承和定义虚函数
【发布时间】:2011-08-20 04:22:39
【问题描述】:

我有一个多重继承场景,没有像这样的虚拟基类:

 Ta  Tb
 |   |
 B   C
  \ /
   A

Ta 和 Tb 是两个不同的模板类,它们都声明了一个名为 f() 的虚函数。我想在 A 范围内覆盖这两个函数,因为我必须在这些方法中与 B 和 C 数据进行交互。但我不知道该怎么做。

class Tb {
protected:
    virtual void f() {};
public:
    void call() {
        this->f();
    };  
};

class Tc {
protected:
    virtual void f() {};
public:
    void call() {
        this->f();
    };
};

class B : public Tb {
public:
    void doSomething() {};
};

class C : public Tc {
private:
    int c;
public:
    void inc() { c++; };
};

class A : public B, public C {
protected:
    void f() { // this is legal but I don't want to override both with the same definition.
        // code here
    }
    // if Tb::f() is called then i want to call C::inc()
    // if Tc::f() is called then i want to call B::doSomething()
public:
    void call() {
        B::call();
        C::call();
    };
};

是否有一种语法可以用不同的定义覆盖这两种方法,还是我必须在 B 和 C 中定义它们?

谢谢

编辑: 我的问题不是不能调用 Tb::f() 或 Tc::f(),而是如果调用 Tb::f() 或 Tc::f(),我想定义两种不同的行为。这些方法由 Tb 和 Tc 本身在其自己的公共方法中调用。 修改了示例,所以可能更清楚我想要做什么......

【问题讨论】:

    标签: c++ multiple-inheritance virtual-functions


    【解决方案1】:

    是否有一种语法可以用不同的定义覆盖这两种方法,还是我必须在 B 和 C 中定义它们?

    简短回答:不。

    您的A:f() 将覆盖Ta::f()Tb::f()

    如果您想要不同的覆盖,唯一的解决方案是插入辅助类 Hb 和 Hc:

    Ta  Tb
    |   |
    B   C
    |   |
    Hb  Hc
     \ /
      A 
    

    Hb可以小到两个函数,只是为了重命名函数:

    class Hb: public B {
       protected: // overrides from Ta
         virtual void f() { Ta_f(); }
    
       protected: // new virtuals
         virtual void Ta_f() = 0;
     };
    

    然后你可以定义A::Ta_f() 做任何你想做的事(包括调用B::f() !)

    【讨论】:

    • 感谢您的建议,我想到了那个解决方案,但是因为它添加了一个层,我对使用它并寻找另一个解决方案感到宽容。但是没有所以我正在使用它。
    • @Gianni 从技术上讲,做你想做的事没有障碍。 C++ 中没有语法可以做到这一点。 (例如,C# 有一种语法可以完全按照您的意愿行事)
    • C# 根本没有多重继承。
    • @Vlad C# 具有多重继承,但仅限于接口。因此,程序员不需要知道它。尽管如此,编译器必须在幕后解决大多数由实现多重继承引起的问题(例如调整 this/self 指针的蹦床函数)。
    【解决方案2】:

    您确实在 A 类中覆盖了这两个。如果您不这样做,除非使用 using 指令明确指定您喜欢的方法,否则就会产生歧义。

    您可以在BC 类中分别覆盖这些方法,但同样,一旦A 类继承了这两个方法,您必须决定应该使用哪一个。

    【讨论】:

    • 你不能从 withing A::f 调度,调用 b::f() 或 c::f() 吗?
    • 这并不能真正回答问题(如何以不同方式覆盖方法),是吗?
    • @Mario:你可以。但更简单的是说using b::f,而不是编写调用基类方法之一的虚拟实现。
    【解决方案3】:

    您是否必须能够将A 替换为TbTc?如果没有,您是否考虑过在A 中使用组合而不是继承?

    如果您需要以这种方式进行替换,您是否考虑过采用简单的方法并只调用两个不同的名称的父方法?由于您想单独覆盖它们,因此表明它们没有做同样的事情。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多