c++ sobrecargado advertencia de función virtual por clang?


Clang emite una advertencia al compilar el siguiente código:

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);
};

La advertencia es:

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

(la advertencia debe estar habilitada, por supuesto).

No entiendo por qué. Tenga en cuenta que descomentar la misma declaración en Base apaga la advertencia. Tengo entendido que dado que las dos funciones get () tienen diferentes firmas, no puede haber ocultación.

¿Es clang correcto? ¿Por qué?

Tenga en cuenta que esto es en macOS X, que ejecuta una versión reciente de Xcode.

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

Actualización: el mismo comportamiento con Xcode 4.6.3.

Author: Jean-Denis Muys, 2013-08-29

4 answers

Esta advertencia está ahí para evitar la ocultación accidental de sobrecargas cuando se pretende sobreescribir. Considere un ejemplo ligeramente diferente:

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
};

Como es una advertencia, no significa necesariamente que sea un error, pero podría indicar uno. Por lo general, tales advertencias tienen un medio de apagarlas al ser más explícitas y dejar que el compilador sepa que usted tenía la intención de lo que escribió. Creo que en este caso se puede hacer lo siguiente:

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);
};
 86
Author: R. Martinho Fernandes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-29 15:55:54

La solución de R. Martinho Fernandes es perfectamente válida si realmente desea llevar el método get() tomando un solo argumento char* al ámbito Derived.

En realidad, en el fragmento que proporcionó, no hay necesidad de métodos virtuales (ya que Base y Derivado no comparten ningún método con la misma firma).

Suponiendo que realmente hay una necesidad de polimorfismo, el comportamiento de ocultación podría ser lo que se pretende. En este caso, es posible desactivar localmente Advertencia de Clang, con el siguiente pragma:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
    // Member declaration raising the warning.
#pragma clang diagnostic pop
 21
Author: Ad N,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-22 14:30:34

Otra forma de desactivar la advertencia manteniendo intacta la interfaz pública de la estructura sería:

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

Esto no permite que un consumidor de Derived llame Derived::get(char* e) mientras silencia la advertencia:

Derived der;
der.get("", 0); //Allowed
der.get("");    //Compilation error
 16
Author: Pedro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-13 08:08:08

Advertencia significa, que no habrá void * get (char * e) función en el ámbito de la clase derivada, causarla oculta por otro método con el mismo nombre. El compilador no buscará la función en las clases base si la clase derivada tiene al menos un método con un nombre especificado, incluso si tiene otros argumentos.

Este código de ejemplo no se compilará:

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

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


int main()
{
    B b;
    b.Foo();
    return 0;
}
 10
Author: WormholeWizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-21 23:01:33