О множественном наследовании и определении виртуальной функции

У меня есть сценарий множественного наследования без виртуальных базовых классов:

 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?

Спасибо

Изменить: Моя проблема заключается не в том, что вызов can not Tb:: f() или Tc:: f(), но я хочу определить два разных поведения, если вызывается Tb:: f() или Tc:: f(). Эти методы называются самими Tb и Tc в собственных публичных методах. Модифицированный пример, поэтому, возможно, более ясно, что я хочу сделать...

Ответы

Ответ 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()!)

Ответ 2

Вы переопределили оба класса A. Если бы вы этого не сделали, была бы двусмысленность, если директива using не используется, чтобы явно указать, какой метод вы предпочитаете.

Вы можете переопределить эти методы отдельно в классах B и C, но опять же, как только класс A наследует и вы должны решить, какой из них следует использовать.

Ответ 3

Вы абсолютно должны иметь возможность заменить A на Tb или Tc? Если нет, рассмотрели ли вы использование композиции в A вместо наследования?

Если вам нужно подставить таким образом, рассмотрите ли вы простой способ и просто назовите родительские методы двумя разными именами? Поскольку вы хотите переопределить их отдельно, указание состоит в том, что они не делают то же самое.