Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override base classes' virtual functions that have identical names in multiple inheritance?

Suppose I have two base classes B1 and B2, and a class D that derives from both B1 and B2 as follows:

class B1 {
public:
  // ...
  virtual void foo() final { cout << "Hello, B1\n"; }
};

class B2 {
public:
  // ...
  virtual void foo() { cout << "Good riddance, B2!\n"; }
};

class D :public B1, public B2 {
  // ...
};

In designing the class D, I want to override the member function called foo() from B2; however, foo() in B1 is marked final and prevents me from overriding foo() in B2. What is the best approach to override foo() from B2?

like image 384
Region Avatar asked Jun 23 '15 04:06

Region


1 Answers

I don't think what you want to do is possible in the manner you've shown in the question. From N3337, §10.3/2 [class.virtual]

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf. ...

D::foo matches all those criteria for B1::foo and B2::foo, hence it overrides both. And since B1::foo is final, the code is ill-formed.

One workaround is to introduce an extra level of inheritance. Define a class, say D2, that derives from B2 and overrides B2::foo. Then D can derive from B1 and D2 instead.

class D2 : public B2{
public:
  virtual void foo() override { cout << __PRETTY_FUNCTION__ << '\n'; }
};

class D :public B1, public D2 
{};

D d;
// d.foo();    // error - ambiguous

D2& d2 = d;
d2.foo();   // calls D2::foo
B2& b2 = d;
b2.foo();   // calls D2::foo

B1& b1 = d;
b1.foo();   // calls B1::foo

Live demo

like image 96
Praetorian Avatar answered Sep 25 '22 10:09

Praetorian