Multiple Inheritance Virtual Challenge

The problem is that it's hard to describe, so the code is better for greater clarity.

struct Base { int b; virtual void foo(){cout << b << endl;} Base(int x) : b(x){} }; struct Derived1 : Base //not virtual { virtual void foo(){/*Derived2 code*/} Derived1() : Base(1){} }; struct Derived2 : Base //not virtual { virtual void foo(){/*Derived2 code*/} Derived2() : Base(2){} }; struct MultiInheritance : Derived1, Derived2 { void bar1() { //needs to access Derived1 Base foo() } void bar2() { //needs to access Derived2 Base foo() } }; 

Suppose that in some strange bizarre scenario, I would like to get the base class MultiInheritance , which has two base classes Derived1 and Derived2 , which share a common non-virtual base class Base .

There are two Base in MultiInheritance , how to specify which Base class I want to get in MultiInheritance ?

The above code seems to work fine several times, but I'm not sure if this behavior is defined or not. If so, how is this implemented by the compiler to meet the needs of polymorphism? On the one hand, virtual calls must lead to the same virtual function table, and on the other hand, if it does not output different answers.

EDIT

I want to emphasize that Base classes must not be virtual

EDIT2

Deep apologies, I seriously misrepresented myself. The code above reflects my original question better.

+5
source share
3 answers

Here is a more illustrative example.

 #include <iostream> using namespace std; template <typename Res, typename Arg> Res& as(Arg& arg) { return arg; } struct Base { virtual void foo() = 0; }; struct Derived1 : Base {}; struct Derived2 : Base {}; struct MoreDerived1 : Derived1 { void foo() { cout << "Derived1\n"; } }; struct MoreDerived2 : Derived2 { void foo() { cout << "Derived2\n"; } }; struct MultiInheritance : MoreDerived1, MoreDerived2 { void bar1() { as<Derived1>(*this).foo(); } void bar2() { as<Derived2>(*this).foo(); } }; int main () { MultiInheritance m; m.bar1(); m.bar2(); } 

This example illustrates that:

  • You do not need to specify which base you need to explicitly use the full inheritance path, just go to the subobject that has an unambiguous base subobject
  • The mechanism of virtual functions operates here. This will not work if you try to call Derived1::foo() .

The as helper function is just syntactic sugar, you can just say

 Derived1& d = *this; d.foo(); 
0
source

This is called the diamond problem.

http://www.cprogramming.com/tutorial/virtual_inheritance.html

If you want to keep the database non-virtual and get the behavior you are looking for now, you can do it inside MultipleInheritance as follows to make sure that you call the foo() function from the correct base class

 struct MultiInheritance : Derived1, Derived2 { void bar1() { Derived1::foo(); } void bar2() { Derived2::foo(); } }; 
+2
source

There are two bases in MultiInheritance, how can I indicate which base class I want to access in MultiInheritance?

You have an ambiguity in which the base object you call in

 void MultiInheritance::bar1(){ foo(); } 

The way to resolve this issue is to tell the compiler where to look for foo.

 void MultiInheritance::bar1(){ Derived1::foo(); // The same foo() as in your question. } 

This is what is achieved with

 void MultiInheritance::bar1() { Derived1& d = *this; 

This is described in the standard in ยง10.2.12. This is clearly defined. Like your chain

 void MultiInheritance::bar1() { Derived1& d = *this; Base& b = *this; 

in the same paragraph.

Unfortunately, the region resolution operator cannot force you to switch from MultiInhteritance directly to Base as

 MultiInheritance::foo(){ Derived1::Base::foo(); 

describes a nested Base class.

To go to the foo () function owned by Base, you use permission resolution syntax in MultiInheritance, as well as in Derived1 and Derived2.

 Derived1()::foo(){ Base::foo; 

If this is inappropriate, the option you proposed is the remaining option.

If so, how is this implemented by the compiler to meet the needs of polymorphism? On the one hand, virtual calls must have the same virtual function table, and on the other hand, if it does, they display different answers.

Compiler implementations are different for the compiler, and as the commentator stated: using vtables for virtual functions is a detail of the implementation. And if the implementation uses the virtual function vtable, for the implementation it is necessary to consider this scenario.

0
source

All Articles