Inaccessible Direct Base' Caused by Multiple Inheritance

Inaccessible direct base' caused by multiple inheritance

This has nothing to do with overriding functions. It has to do with conversions. It really doesn't have to do with accessibility (i.e "private" or such) directly either. Here is a simpler example

struct A { int a; };
struct B : A { };
struct C : B, A { }; // direct A can't be referred to!

You can refer to the indirect A object by first converting to B and then to A:

B *b = &somec;
A *a = b;

You cannot do such with the direct A object. If you try to directly convert to A, it will have two possibilities. It follows that it is impossible to refer to the non-static data members of the direct A object given a Derived object.

Notice that accessibility is orthogonal to visibility. Something can be accessible even tho it's not visible (for example by refering to it by a qualified name), and something can be visible even though it's not accessible. Even if all the above derivations would be declared private, the problem would still show up: Access is checked last - it won't influence name lookup or conversion rules.

Also, anyone can cast to an unambiguous private base class with defined behavior (the C++ Standard makes an exception for this) using a C-style cast, even if normally access wouldn't be granted to do so. And then there are still friends and the class itself that could freely convert.

Warning: direct base class inaccessible in derived due to ambiguity; is this serious?

template <typename T>
class ScrollSpell : public T, public SpellFromScroll {};

Here, T = Spell, so the ScrollSpell class has the Spell class as a direct, non-virtual base class, and also as a virtual base class through SpellFromScroll. That is the ambiguity. Declaring the base class T as virtual might solve the problem.

Also I don't really understand the point behind the design, so that might introduce some completely new issues.

c++ Access to base class members with diamond inheritance syntax

This is not a diamond scheme, this is a "cursed diamond". Inheritance diamond doesn't have direct line from base class to most derived class. You can't access upper in any way due to ambiguous inheritance. And you already got two instances of upper inside of two "flanking" classes.

Some may expect that

a.lower::upper::base = 1; 

should work. It should not. lower as a namespace contains two uppers from left and right and one from its own declaration. While you can specify namespace for the upper inside of left and right, you can't do that for the direct "third wheel" in that parenthood. It's just same as if you tried to do this:

/*       upper
/ \
left right
\ /
lower
*/

a.upper::base = 1;

In this case you may make it work, but this kind of approach to architecture is questionable. As it raises the question if you actually are in dire need of the component-entity pattern.

/*       upper
/ | \
left center right
\ | /
lower
*/

In other words: while having more than two parents in relationship for sake of grandparent being able to reach its grandchild is interesting, on practice bacteria with their plasmids have found a better way.



Related Topics



Leave a reply



Submit