In diesem Beispiel werden Klassen Foo
und Bar
aus einer Bibliothek bereitgestellt. Meine Klasse Baz
erbt von beiden.
struct Foo
{
void do_stuff (int, int);
};
struct Bar
{
virtual void do_stuff (float) = 0;
};
struct Baz : public Foo, public Bar
{
void func ()
{
do_stuff (1.1f); // ERROR HERE
}
};
struct BazImpl : public Baz
{
void do_stuff (float) override {};
};
int main ()
{
BazImpl () .func ();
}
Ich erhalte den Kompilierungsfehler, reference to ‘do_stuff’ is ambiguous
der mir falsch erscheint, da die beiden Funktionssignaturen völlig unterschiedlich sind. Wenn do_stuff
es nicht virtuell wäre, könnte ich anrufen Bar::do_stuff
, um es zu disambiguieren, aber dies bricht den Polymorphismus und verursacht einen Linkerfehler.
Kann ich func
den virtuellen Anruf tätigen , do_stuff
ohne Dinge umzubenennen?
Antworten:
Du kannst das:
Getestet mit wandbox gcc spätestens und es kompiliert gut. Ich denke, es ist der gleiche Fall mit Funktionsüberladungen. Wenn Sie eine überladen, können Sie keine Basisklassenimplementierungen ohne verwenden
using
.Tatsächlich hat dies nichts mit virtuellen Funktionen zu tun. Das folgende Beispiel hat den gleichen Fehler
GCC 9.2.0 error: reference to 'do_stuff' is ambiguous
:Mögliche verwandte Frage
quelle
Namenssuche und Überlastungsauflösung sind unterschiedlich. Der Name muss zuerst in einem Bereich gefunden werden, dh wir finden müssen ,
X
so dass der Namedo_stuff
zu aufgelöst wirdX::do_stuff
- unabhängig von der Nutzung der Namens - und dann Auflösung wählt zwischen den verschiedenen Erklärungen von ÜberlastungX::do_stuff
.Der Prozess ist nicht alle solche Fälle zu identifizieren
A::do_stuff
,B::do_stuff
usw. , die sichtbar sind, und dann die Überladungsauflösung unter der Vereinigung , dass zuführen. Stattdessen muss ein einzelner Bereich für den Namen identifiziert werden.In diesem Code:
Baz
enthält den Namen nichtdo_stuff
, sodass Basisklassen nachgeschlagen werden können. Der Name kommt jedoch in zwei verschiedenen Basen vor, sodass bei der Namenssuche kein Bereich identifiziert werden kann. Wir kommen nie so weit zur Überlastungsauflösung.Das vorgeschlagene Update in der anderen Antwort funktioniert, da es den Namen
do_stuff
in den Bereich vonBaz
einführt und außerdem zwei Überladungen für den Namen einführt. Die Namenssuche bestimmt also, dass diesdo_stuff
bedeutet,Baz::do_stuff
und dann wählt die Überlastungsauflösung aus den beiden Funktionen aus, die als bekannt sindBaz::do_stuff
.Abgesehen davon ist das Abschatten eine weitere Folge der Namenssuche (keine Regel an sich). Die Namenssuche wählt den inneren Bereich aus, sodass alles im äußeren Bereich nicht übereinstimmt.
Ein weiterer komplizierender Faktor tritt auf, wenn eine argumentabhängige Suche im Spiel ist. Um es kurz zusammenzufassen: Die Namenssuche wird mehrmals für einen Funktionsaufruf mit Argumenten des Klassentyps durchgeführt - der Basisversion, wie in meiner Antwort beschrieben, und dann erneut für den Typ jedes Arguments. Dann geht die Vereinigung der gefundenen Bereiche in den Überlastsatz. Dies gilt jedoch nicht für Ihr Beispiel, da Ihre Funktion nur Parameter vom integrierten Typ enthält.
quelle