En C++,l'accès aux membres de la classe doit être sans ambiguïté. Le contrôle d'accès n'intervient pas en ce qui concerne l'ambiguïté.
class A{ int a; void f(); public: void g(); }; class B{ int b; void f() public: int a; }; class C: public A, public B{ int b; // occulte B::b public: void g(int); // occulte A::g() }c; //... c.g(); // interdit A::g() hors de portée c.g(i); // ok C::g(int) c.a; // interdit A::a ou B::a ? c.B::a; // ok visible c.A::a; // interdit A::a est privé
Pour associer un nom de fonction à sa déclaration le compilateur procédera ainsi:
En partageant les noms, l'héritage virtuel permet aussi d'éviter les ambiguïtés:
class V{ public: int v;}; class A{ public: int a;}; class D1: public A, virtual public V{}; class D2: public A, virtual public V{}; class X:public D1, public D2{ public:void f(); }; void X::f(){ v++; // partage de V.v a++; // a de D1 ou de D2 };
Le C++ définit une relation de domination entre les noms :
un nom B::f
domine un nom A::f
si la classe
A
est une classe de base pour B
(c'est la
relation d'héritage telle qu'elle a été définie ci-dessus).
En ce qui concerne l'héritage ``non-virtuel'' (simple ou multiple)
c'est la règle standard : on parcourt la relation d'héritage, et on
associe le nom à la déclaration la plus proche pour cette relation
d'héritage ; avec l'héritage virtuel, cela signifie, que si un nom
dans une classe de base héritée virtuellement est redéfini par un des
descendants c'est cette redéfinition qui sera choisie :
class V{ public: void f(); int x; }; class B : public virtual V{ public: void f(); int x; }; //cache V::f et V::x class C: public virtual V {}; class D: public B, public C { void essai(); } void D::essai(){ x; // ici B::x domine V::x f(); // B::f() domine V::f() }