La réponse de Johannes couvre les faits de base. Mais il y a un peu plus. Alors, pensez à
struct Base
{
Base(int) {}
void foo() const {}
};
struct Intermediate: Base
{
Intermediate(int x)
: Base(x)
{}
};
struct Derived: Intermediate, Base
{
Derived(int x)
: Intermediate(x)
, Base(x) // OK
{}
};
int main()
{
Derived o(667);
o.foo(); // !Oops, ambiguous.
o.Base::foo(); // !Oops, still ambiguous.
}
Quand je compile je reçois, comme maintenant (après la réponse de Johannes), vous attendre,
C:\test> gnuc x.cpp
x.cpp:15: warning: direct base 'Base' inaccessible in 'Derived' due to ambiguity
x.cpp: In function 'int main()':
x.cpp:25: error: request for member 'foo' is ambiguous
x.cpp:4: error: candidates are: void Base::foo() const
x.cpp:4: error: void Base::foo() const
x.cpp:26: error: 'Base' is an ambiguous base of 'Derived'
C:\test> msvc x.cpp
x.cpp
x.cpp(15) : warning C4584: 'Derived' : base-class 'Base' is already a base-class of 'Intermediate'
x.cpp(2) : see declaration of 'Base'
x.cpp(7) : see declaration of 'Intermediate'
x.cpp(25) : error C2385: ambiguous access of 'foo'
could be the 'foo' in base 'Base'
or could be the 'foo' in base 'Base'
x.cpp(25) : error C3861: 'foo': identifier not found
C:\test> _
Comment résoudre dépend si elle est bien avec un seul sous -objet de la classe Base
(comme c'est le cas lorsque Base
est une interface pure), ou Intermediate
nécessite vraiment son propre sous-objet Base
. Ce dernier cas, deux sous-objets Base
, n'est probablement pas ce que vous voulez, mais si vous voulez alors alors une cure est d'introduire encore une autre classe intermédiaire, disons ResolvableBase
.
Comme:
struct Base
{
Base(int) {}
void foo() const {}
};
struct Intermediate: Base
{
Intermediate(int x)
: Base(x)
{}
};
struct ResolvableBase: Base
{
ResolvableBase(int x): Base(x) {}
};
struct Derived: Intermediate, ResolvableBase
{
Derived(int x)
: Intermediate(x)
, ResolvableBase(x)
{}
};
int main()
{
Derived o(667);
o.ResolvableBase::foo(); // OK.
}
Dans le premier cas, où par exempleBase
est une interface et un seul sous-objet Base
est nécessaire, vous pouvez utiliser l'héritage virtuel.
L'héritage virtuel ajoute généralement un certain temps d'exécution, et Visual C++ ne l'aime pas trop.
Mais il vous permet de « héritez dans » une mise en œuvre d'une interface, comme en Java et C#:
struct Base
{
Base(int) {}
virtual void foo() const = 0;
};
struct Intermediate: virtual Base
{
Intermediate(int x)
: Base(x)
{}
void foo() const {} // An implementation of Base::foo
};
struct Derived: virtual Base, Intermediate
{
Derived(int x)
: Base(x)
, Intermediate(x)
{}
};
int main()
{
Derived o(667);
o.foo(); // OK.
}
Subtilité: J'ai changé la liste d'héritage ordre afin d'éviter g ++ sillywarnings sur l'ordre d'initialisation. Désagrément: Visual C++ émet des erreurs C4250 sur l'héritage (de l'implémentation) via la dominance. C'est comme "avertissement: vous utilisez une fonction principale standard". Eh bien, éteignez-le.
Vive & HTH.,
ne est pas un compilateur de correction d'erreurs de son [juste un avertissement] (http://ideone.com/Pe0nK). –
J'imagine qu'appeler Derived-> YourMethod (5) devrait être bien ... après tout, dans la Base et l'Intermédiaire, YuorMethod est virtuel, alors pourquoi ne pouvez-vous pas définir votre propre implémentation? Vous n'appelez d'aucune façon les fonctions de base, donc le tihng public privé ne devrait pas avoir d'importance? – thecoshman
@Prasoon: Édité. – nakiya