Frage

Ich habe eine Templat-Klasse, die eine Aktion auf der Klasse, die als Template-Argument angegeben wird. Für einige meiner Klassen möchte ich ‚Gruppe‘ die Funktionalität in einer Klasse, um es für den Anrufer einfacher. In der Tat sieht der Code so etwas wie diese (Name wurde geändert):

template<typename T>
class DoSomeProcessing
{
public:
   process(T &t);
};

class ProcessingFrontEnd : public DoSomeProcessing<CustomerOrder>, public DoSomeProcessing<ProductionOrder>
{
};

Das Problem ist, dass, wenn ich rufe ProcessingFrontEnd :: Prozess mit einem Customer als Argument, dass der Compiler darüber beschwert.

Ich habe versucht, das Problem in einer kleineren Testanwendung zu reproduzieren. Dies ist der Code:

#include <vector>

class X : public std::vector<char>
        , public std::vector<void *>
{
};

int main(void)
{
X x;
x.push_back('c');
return 0;
}

Und in der Tat, wenn diese kompiliert wird, Microsoft VS2010 Compiler gibt diesen Fehler:

test.cpp
test.cpp(11) : error C2385: ambiguous access of 'push_back'
        could be the 'push_back' in base 'std::vector<char,std::allocator<char> >'
        or could be the 'push_back' in base 'std::vector<void *,std::allocator<void *> >'
test.cpp(11) : error C3861: 'push_back': identifier not found

Getestet habe ich diese Testanwendung mit verschiedenen Typen (char + void *, Doppel + void *) und anderen Argumenten im Aufruf ( ‚c‘, 3,14), aber die Fehlermeldung ist immer das gleiche.

Getestet habe ich diese mit VS2005 und VS2010 aber ich habe immer die gleichen Fehler.

Warum kann der Compiler die korrekte Funktion bestimmen zu nennen? Was macht diese für den Compiler verwirrend? Oder ist es nur ein Fehler in den Microsoft-Compiler?

EDIT: Wenn ich ausdrücklich hinzufügen 2 push_back Methoden zu meiner Klasse, wie folgt aus:

class X : public std::vector<char>
        , public std::vector<void *>
{
public:
   void push_back(char c) {}
   void push_back(void *p) {}
};

Der Compiler beschwert sich nicht mehr. So mit diesen Methoden kann er deutlich zwischen einem Charakter unterscheiden und hohlraum Zeigern. Warum kann er dies tun, wenn die beiden push_back Methoden aus dem Elternteil vererbt werden?

War es hilfreich?

Lösung

Das ist von Entwurf. Der Compiler versucht, nicht zu lösen überladene Funktionen, weil diese nicht überladen Funktionen. Der Standard ist wirklich klar, dass (Siehe 10.2.2). Wenn der gleiche Name wird in zwei gefunden verschiedene Basen, dann ist es eine Mehrdeutigkeit, auch wenn sie könnte richtig mit dem Anruf gelöst (das heißt in dein Fall). Gleiche genannten Funktionen in verschiedenen Klassen werden in der Regel ganz unterschiedliche Zwecke haben und damit die Auswahl zwischen ihnen nicht auf der Grundlage gemacht werden soll ihre Argumente. Es gibt viele gute Gründe, nicht zu zulassen, dass, aber hier ist eine.

Stellen Sie sich Ihre Klasse C ergibt sich aus A und B und diese beiden Basisklassen kommen aus zwei verschiedenen Bibliotheken. Wenn der Autor B fügt eine neue Funktion der Klasse, kann es der Benutzer-Code brechen, indem einen Anruf von einem Umleiten :: foo () zu B :: foo (), wenn letzteres ist ein besseres Spiel.

Wenn Sie die beiden Funktionen wollen in der gleichen Art und Weise behandelt werden, sie würden Teil einer einzelnen Klasse sein, wenn, dann ist der beste Weg, es zu tun ist, mit der Verwendung von Erklärungen in der abgeleiteten Klasse. Fügen Sie einfach

using std::vector<char>::push_back;
using std::vector<void *>::push_back;

zur Deklaration der Klasse X.

Andere Tipps

Ich glaube, Sie afoul der C laufen ++ Regeln zu überlasten, die verbieten Überlastung über Klassen . Sie würden die gleichen Ergebnisse erhalten, wenn Ihre Template-Klassen waren zwei getrennte Klassen, jede mit ihrem eigenen process(CustomerOrder) und process(ProductionOrder) Mitglied.

Die Abhilfe ist explizit using Anweisungen innerhalb der abgeleiteten Klasse, die von jedem der Vorlage Basisklassen in jeder Überlastung ziehen.

Wie wird der Compiler wissen soll, welcher Prozess die Sie anrufen möchten? Es gibt zwei Möglichkeiten. Wollen Sie beide, eine oder das andere?

Sie müssen Prozess in der abgeleiteten Klasse außer Kraft zu setzen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top