„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > ## Warum führt die Mehrfachvererbung mit Vorlagenbasisklassen zu Mehrdeutigkeiten bei der Auflösung von Mitgliedsfunktionen?

## Warum führt die Mehrfachvererbung mit Vorlagenbasisklassen zu Mehrdeutigkeiten bei der Auflösung von Mitgliedsfunktionen?

Veröffentlicht am 08.11.2024
Durchsuche:438

## Why Does Multiple Inheritance with Template Base Classes Cause Ambiguity in Member Function Resolution?

Mehrdeutigkeit bei der Disambiguierung von Mehrfachvererbung

Beim Umgang mit Mehrfachvererbung mithilfe von Vorlagenbasisklassen entsteht ein potenzielles Problem hinsichtlich der Auflösung mehrdeutiger Mitgliedsfunktionen. Stellen Sie sich das folgende Szenario vor:

template 
class Base {
public:
  template 
  typename std::enable_if::value>::type foo() {
    std::cout 

Hier ist die Funktion foo() nur aufrufbar, wenn der Vorlagenparameter mit einem der Typen im Types-Paket übereinstimmt. Wenn nun eine abgeleitete Klasse von mehreren Basisklassen mit nicht überlappenden Typsätzen erbt, kann der Compiler beim Auflösen des foo()-Aufrufs auf Mehrdeutigkeiten stoßen.

struct Derived: public Base,
                public Base
{};

In diesem Fall würde der Aufruf Derived().foo() idealerweise die foo()-Memberfunktion von Base aufrufen. Allerdings melden sowohl GCC als auch Clang eine Mehrdeutigkeit.

Warum der Compiler die Mehrdeutigkeit nicht auflösen kann

Der Kompilierungsfehler entsteht aufgrund der Zusammenführungsregeln für die Suche nach Mitgliedsfunktionen. Gemäß dem C-Standard durchsucht der Suchprozess nacheinander die Basisklassen, wenn die Memberfunktion nicht in der abgeleiteten Klasse selbst deklariert ist. Wenn sich jedoch die Deklarationssätze in den Basisklassen unterscheiden, wird die Zusammenführung mehrdeutig.

Im gegebenen Szenario deklariert die abgeleitete Klasse Derived foo() nicht explizit, sodass der Compiler die Nachschlagesätze aus dem zusammenführen muss zwei Basisklassen. Da die Basisklassen unterschiedliche Deklarationssätze für foo() enthalten, führt die Zusammenführung zu Mehrdeutigkeiten.

Solutions

Um diese Mehrdeutigkeit aufzulösen, besteht eine Möglichkeit darin, using-Deklarationen zu verwenden in der abgeleiteten Klasse, um die gewünschten Mitgliedsfunktionen explizit zu importieren. Dies erfordert jedoch, dass der Benutzer diese Deklarationen hinzufügt, was bei großen Typlisten ausführlich und unpraktisch sein kann.

struct Derived: public Base,
                public Base
{
    using Base::foo;
    using Base::foo;
};

Alternativ kann man eine Hilfsklasse verwenden, die die Mitgliedsfunktionen aller Basisklassen sammelt und zusammenführt, sodass die abgeleitete Klasse direkt darauf zugreifen kann.

template 
struct BaseCollector : Bases...
{
  using Bases::foo...;
};

struct Derived : BaseCollector, Base>
{};

Bei diesem Ansatz muss der Benutzer keine zusätzlichen Deklarationen hinzufügen, um die Mehrdeutigkeit aufzulösen. Die BaseCollector-Klasse führt effektiv die Deklarationssätze aller Basisklassen zusammen und macht die foo()-Funktion ohne Mehrdeutigkeit für die abgeleitete Klasse verfügbar.

Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3