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 upper
s 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
Using Quaternions for Opengl Rotations
How to Set the Baud Rate to 307,200 on Linux
Scope of Using Declaration Within a Namespace
Does This Really Break Strict-Aliasing Rules
Why Is Modifying a String Through a Retrieved Pointer to Its Data Not Allowed
Why Do Functions Need to Be Declared Before They Are Used
Is a Constexpr Array Necessarily Odr-Used When Subscripted
Is Std::Vector Memory Freed Upon a Clear
Why Does C++ Not Have a Const Constructor
How to Redirect Output to a File with Createprocess
Inaccessible Direct Base' Caused by Multiple Inheritance
How to Return a Char Array from a Function
Specify Template Parameters at Runtime
Scope VS Life of Variable in C