2010-01-13 10 views
6

Gibt es ein Problem mit teilweise überschreiben eine Reihe von virtuellen Funktionen von einer Basisklasse definiert?Probleme mit partiellen Klassenfunktionsüberschreibungen in C++

Mein Compiler bietet die folgende Warnung:

overloaded virtual function "MyBaseClass::setValue" is only partially overridden in class "MyDerivedClass". 

Die Klassen dies wie folgt aussehen:

class MyBaseClass 
{ 
public: 
    virtual void setValue(int); 
    virtual void setValue(SpecialType*); 
} 

class MyDerivedClass : public MyBaseClass 
{ 
public: 
    virtual void setValue(int); 
} 

Die einfache Art und Weise dieser Warnung loszuwerden, ist, verschiedene Namen für die Basisfunktionen zu verwenden, aber ich wollte wissen, ob es einen zwingenden Grund gab, diese spezielle Warnung zu beheben. Ich glaube nicht, dass dies gegen den C++ - Standard verstößt. Meine Vermutung ist, dass es einen Programmierer warnt, dass er möglicherweise vergessen hat, das Verhalten für alle möglichen Eingabetypen zu implementieren. In unserem Fall ist es beabsichtigt, einige der spezifischen Typen auszuschließen.

Würdest du davon abraten, diese Warnung ganz zu unterdrücken?

+0

Wenn Sie unterschiedliche Namen für die Basisfunktionen unter Berücksichtigung verwenden, mit allen Mitteln tun. Das deutet darauf hin, dass MyBaseClass :: setValue (int) eine andere konzeptionelle Sache von MyDerivedClass :: setValue (int) macht, und das ist schlecht. Virtuelle Funktionen sollten das gleiche in basis und abgeleitet tun, oder Sie können schwer zu findende Bugs aus kleinen Änderungen bekommen. –

+0

In meinem speziellen Fall machen sie konzeptionell dasselbe. Das Umbenennen könnte etwas wie setValueFromInt() setValueFromSpecialType() sein, das nicht so sauber aussehen würde. Ich würde viel lieber die in einer der Antworten beschriebenen using-Anweisungen verwenden. Derzeit wird die Umsetzung dieses Ansatzes untersucht. –

Antwort

13

Die Überschreibung für setValue(int) versteckt setValue(SpecialType*) der Basisklasse (die C++ FAQ Lite sehen), so dass, wenn Sie versuchen, setValue(new SpecialType()) anrufen wird eine Fehlermeldung angezeigt.

Sie können dies vermeiden, indem das Hinzufügen einer using Richtlinie auf die abgeleitete Klasse, die „Einfuhr“ die Überlast von der Basisklasse:

class MyDerivedClass : public MyBaseClass 
{ 
public: 
    using MyBaseClass::setValue; 
    virtual void setValue(int); 
}; 
+0

+1 für das tatsächliche Zeigen, wie man die Versionen NICHT umschreibt, die du nicht interessierst, sich zu spezialisieren. –

+0

Die using-Anweisung funktioniert für mich. Ich entwickle für mehrere Plattformen. Ich habe Probleme, Microsoft Visual Studio 6.0 dazu zu bringen, sich über dieses spezielle Codeproblem zu beschweren. Selbst mit der strengsten Warnstufe kann ich mich nicht beschweren. Jeder mit einer Idee, wie man diesen Compiler dazu bringt, eine Warnung auszuspucken? –

6

Die Warnung ist korrekt, sie heißt "Name Versteckt". Eine Variable vom Typ MyDerivedClass kann nicht setValue(SpecialType*) aufrufen.


Jetzt werde ich eklatant someone else's blog Abzocke:

Überladen und den Namen C++

In einem Telefongespräch mit Brad gestern Abend versteckt in, erzählte er mir von einem fremden Problem, das er in seinem neuen C++ - Job angetroffen hat. Zugegeben, es ist wahrscheinlich keine große Sache für Leute mit umfangreicher C++ - Erfahrung, aber denen von uns, die in verwalteten Code-Welten leben, schien das seltsam. Wenn Sie in C++ eine Klasse mit einer überladenen Methode haben (Elementfunktion, wie immer Sie sie aufrufen möchten) und diese Methode dann erweitern und überschreiben, müssen Sie alle überladenen Methoden überschreiben.

Ich verstehe den Fall, in dem Sie eine Methodensignatur in einer untergeordneten Klasse geändert haben, wodurch die etablierte Schnittstelle ungültig wird. In diesem Fall erscheint es jedoch nicht intuitiv, da Sie die Schnittstelle nicht ändern, sondern selektiv überschreiben. Was ist anders.

Zum Beispiel:

class FirstClass 
{ 
public: 
     virtual void MethodA (int); 
     virtual void MethodA (int, int); 
}; 

void FirstClass::MethodA (int i) 
{ 
    std::cout << "ONE!!\n"; 
} 

void FirstClass::MethodA (int i, int j) 
{ 
    std::cout << "TWO!!\n"; 
} 

Einfach Klasse hier mit zwei Methoden (oder einer überladenen Methode). Sie möchten die zweiparametrige Version außer Kraft zu setzen, so dass Sie mit den folgenden fortsetzen:

class SecondClass : public FirstClass 
{ 
public: 
    void MethodA (int); 
}; 

void SecondClass::MethodA (int i) 
{ 
    std::cout << "THREE!!\n"; 
} 

Nun, wenn Sie eine Instanz von Second verwenden, die meisten Java oder C# Programmierer könnte annehmen, dass Sie anrufen:

int main() 
{ 
    SecondClass a; 
    a.MethodA (1); 
    a.MethodA (1, 1); 
} 

Allerdings wird der zweite Anruf nicht funktionieren, da die zweiparametrige MethodA nicht sichtbar ist. Sie können einen Zeiger und einen Upcast auf FirstClass erhalten, aber Ihre SecondClass-Instanz erbt die nicht überschriebenen Methoden nicht direkt.

0

Es ist klar, dass der Compiler Sie warnen will: Sie eine Unterklasse geschaffen, verhält sich anders, wenn Sie ihm eine int geben, aber Sie haben sein Verhalten nicht geändert, wenn Sie ihm eine SpecialType* geben.

Obwohl diese könnte die Absicht sein, ist es sehr sehr möglich, dass das geänderte Verhalten auch für die anderen überladenen virtuellen Funktionen benötigt wird.

Ich wünschte, der Compiler hatte mich härter gewarnt, die Zeit habe ich ignoriert! Meine überschriebene Methode erwies sich als Kompilierung und funktionierte in meinem Szenario gut, aber einige andere Szenarien gingen wirklich falsch, weil die Überladung nicht überschrieben wurde.

Denken Sie zweimal nach, bevor Sie diese Warnung deaktivieren!

Wenn Sie das ursprüngliche Verhalten gehalten wollen, ist es einfach, nur die Funktion Eltern zu nennen:

class MyDerivedClass : public MyBaseClass { 
    virtual void setValue(int); 
    // explicit: keep original behavior for SpecialType 
    virtual void setValue(SpecialType* p) { MyBaseClass::setValue(p); } 
}; 
+0

Ich verstehe, dass Warnungen wichtig sind und versuchen, mich vor etwas zu warnen, das schiefgehen kann. Die Absicht meiner Frage war herauszufinden, warum die Warnung für den Designer wichtig ist und welche Fallstricke auftreten können, indem man sie ignoriert/zum Schweigen bringt. –