La respuesta de Johannes cubre los hechos básicos. Pero hay un poco más. Por lo tanto, considere
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.
}
Cuando compilo consigo, ya que por ahora (después de la respuesta Johannes') que se puede esperar,
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> _
Cómo resolver dependerá de si todo está bien con un solo sub -objeto de la clase Base
(como es el caso cuando Base
es una interfaz pura), o Intermediate
realmente requiere su propio sub-objeto Base
.
El último caso, dos sub-objetos Base
, probablemente no es lo que quieres, pero si quieres eso, entonces una cura es introducir otra clase intermedia, por ejemplo, ResolvableBase
.
térmica:
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.
}
En el primer caso, donde por ejemplo,Base
es una interfaz y solo se necesita un subobjeto Base
, puede usar la herencia virtual.
La herencia virtual generalmente agrega un poco de sobrecarga de tiempo de ejecución, y Visual C++ no es muy aficionado a ella.
sino que le permite "Heredar" una implementación de una interfaz, como en Java y 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.
}
Sutileza: Me cambió el orden de la lista de herencia con el fin de evitar g ++ sillywarnings sobre el orden de inicialización.
Molesto: Visual C++ emite un tonto C4250 sobre la herencia (de la implementación) a través de la dominación. Es como "advertencia: estás usando una función principal estándar". Oh, bueno, solo apágalo.
Saludos & HTH.,
No es un error del compilador su [sólo una advertencia] (http://ideone.com/Pe0nK). –
Me imagino que llamar a Derived-> YourMethod (5) debería estar bien ... después de todo, tanto en Base como en Intermedio, YuorMethod es virtual, entonces ¿por qué no puedes definir tu propia implicación? ¿No estás llamando a las funciones base de ninguna manera, por lo que el asunto público privado no debería importar? – thecoshman
@Prasoon: Editado. – nakiya