web-dev-qa-db-de.com

c ++ überladene virtuelle Funktionswarnung von clang?

clang gibt eine Warnung aus, wenn der folgende Code kompiliert wird:

struct Base
{
    virtual void * get(char* e);
//    virtual void * get(char* e, int index);
};

struct Derived: public Base {
    virtual void * get(char* e, int index);
};

Die Warnung lautet:

warning: 'Derived::get' hides overloaded virtual function [-Woverloaded-virtual]

(Diese Warnung muss natürlich aktiviert sein).

Ich verstehe nicht warum. Beachten Sie, dass das Deaktivieren derselben Deklaration in Base die Warnung beendet. Ich verstehe, dass es kein Verstecken geben kann, da die beiden get () - Funktionen unterschiedliche Signaturen haben.

Ist clang richtig? Warum?

Beachten Sie, dass dies unter MacOS X geschieht und eine aktuelle Version von Xcode ausführt.

clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)

Update: Gleiches Verhalten mit Xcode 4.6.3.

64
Jean-Denis Muys

Diese Warnung soll verhindern, dass Überlastungen versehentlich ausgeblendet werden, wenn ein Überschreiben beabsichtigt ist. Betrachten Sie ein etwas anderes Beispiel:

struct chart; // let's pretend this exists
struct Base
{
    virtual void* get(char* e);
};

struct Derived: public Base {
    virtual void* get(chart* e); // typo, we wanted to override the same function
};

Da es sich um eine Warnung handelt, bedeutet dies nicht unbedingt, dass es sich um einen Fehler handelt, es kann sich jedoch um einen Fehler handeln. Normalerweise haben solche Warnungen die Möglichkeit, sie auszublenden, indem sie expliziter sind und dem Compiler mitteilen, dass Sie beabsichtigt haben, was Sie geschrieben haben. Ich glaube in diesem Fall können Sie Folgendes tun:

struct Derived: public Base {
    using Base::get; // tell the compiler we want both the get from Base and ours
    virtual void * get(char* e, int index);
};
107

R. Martinho Fernandes Die Lösung ist vollkommen gültig, wenn Sie die get() -Methode mit einem einzelnen char * -Argument in den Geltungsbereich von Derived bringen möchten.

Tatsächlich sind in dem von Ihnen bereitgestellten Snippet keine virtuellen Methoden erforderlich (da Base und Derived keine Methode mit derselben Signatur gemeinsam nutzen).

Unter der Annahme, dass tatsächlich ein Bedarf an Polymorphismus besteht, könnte das Versteckverhalten dennoch das sein, was beabsichtigt ist. In diesem Fall ist es möglich, Clangs Warnung mit dem folgenden Pragma lokal zu deaktivieren:

#pragma clang diagnostic Push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
    // Member declaration raising the warning.
#pragma clang diagnostic pop
22
Ad N

Eine andere Möglichkeit, die Warnung zu deaktivieren und die öffentliche Strukturschnittstelle intakt zu halten, wäre:

struct Derived: public Base
{
    virtual void * get(char* e, int index);
private:
    using Base::get;
};

Dies verhindert, dass ein Verbraucher von DerivedDerived::get(char* e) aufruft, während die Warnung stummgeschaltet wird:

Derived der;
der.get("", 0); //Allowed
der.get("");    //Compilation error
21
Pedro

Warnung bedeutet, dass es im Bereich der abgeleiteten Klasse keine void * get (char * e) -Funktion gibt, da diese durch eine andere Methode mit demselben Namen ausgeblendet wird. Der Compiler sucht in Basisklassen nicht nach Funktionen, wenn die abgeleitete Klasse über mindestens eine Methode mit dem angegebenen Namen verfügt, selbst wenn sie andere Argumente enthält.

Dieser Beispielcode wird nicht kompiliert:

class A
{
public:
    virtual void Foo() {}
};

class B : public A
{
public:
    virtual void Foo(int a) {}
};


int main()
{
    B b;
    b.Foo();
    return 0;
}
12
WormholeWizard