Ich habe ein Ergebnis, dass ich nicht von multiple Vererbung erwartet, virtual
Methoden und Zeiger auf Basisklassen.Multiple Vererbung, virtuelle Methoden Kollision und Zeiger aus Basisklassen
Mit d.getStr()
, wenn d
eine derived
Instanz ist, die base_2
Version genannt wird, wie ich erwartet hatte.
Mit p->getStr()
, wenn p
ist ein Zeiger auf eine derived
Instanz (oder einen Zeiger auf base_2
auf eine derived
Beispiel zeigt), die base_2
Version genannt wird, wie ich erwartet hatte.
Aber mit p->getStr()
, wenn p
ein Zeiger auf ein base_1
ist auf ein derived
Beispiel zeigt, die base_1
Version genannt wird und ich war überzeugt, die base_2
Version genannt würde (dank der using
und die Tatsache, dass getStr()
sind virtual
Methoden) .
Das folgende ist ein einfaches Beispiel:
#include <iostream>
struct base_1
{
virtual std::string getStr() const
{ return "string from base 1"; }
};
struct base_2
{
virtual std::string getStr() const
{ return "string from base 2"; }
};
struct derived : public base_1, public base_2
{
using base_2::getStr;
};
int main()
{
derived d;
derived * dp = &d;
base_1 * bp1 = &d;
base_2 * bp2 = &d;
std::cout << "from derived: " << d.getStr() << std::endl;
std::cout << "from derived pointer: " << dp->getStr() << std::endl;
std::cout << "from base_1 pointer: " << bp1->getStr() << std::endl;
std::cout << "from base_2 pointer: " << bp2->getStr() << std::endl;
}
Die Ausgabe ist die folgende
from derived: string from base 2
from derived pointer: string from base 2
from base_1 pointer: string from base 1
from base_2 pointer: string from base 2
Ich weiß, dass der Anruf von base_2
Version aufzuzwingen, die ich in derived
die folgende Methode hinzufügen
std::string getStr() const
{ return base_2::getStr(); }
aber meine Fragen sind:
1) Warum ignoriert der Zeiger auf (verweist auf eine abgeleitete Instanz) die using
-Anweisung und ruft die base_1
-Version von getStr()
auf?
2) Gibt es eine Möglichkeit, die base_2
Version von getStr()
, zu verhängen, wenn derived
weise durch einen base_1
Zeiger verwendet wird, ohne getStr()
neu zu definieren?
--- EDIT ---
Danke für die Antworten.
Ich verstehe, dass Sie beschreiben, was passiert, aber meine Zweifel ist: beschreibt die Sprache (der Standard) diesen Aspekt? Oder ist es ein undefinierter Teil?
Ich meine: Wenn ich die using
Richtlinie entfernen, erhalte ich einen Kompilierungsfehler (error: request for member getStr is ambiguous
), von d.getStr()
und von dp->getStr()
, da der Compiler nicht weiß, welche Version von getStr()
zu wählen.
Aber getStr()
sind virtual
Methoden. Also (ich war davon überzeugt) sollte ein Basiszeiger die abgeleitete Version von ihnen verwenden. Aber wir haben ein paar kollidierende Methoden.
Aus der Sicht der Sprache (Standard) ist eine base_1
(oder) der Zeiger autorisiert (oder verpflichtet), wählen Sie eine der beiden Versionen der kollidierenden Methoden ignorieren die anderen?
Vielleicht irre ich aber scheint mir, dass auf diese Weise die virtual
Methoden als nicht virtual
Methoden verwaltet werden.
'using' hilft nur im visibity. Es macht die virtuelle Basisfunktion nicht abgeleitet oder sieht so aus. – Arunmu