2012-05-08 20 views
6

he visto código de ejemplo como esto antesespecificar el tipo de parámetro de función, pero no variables

class C 
{ 
    C(); 
    ~C(); 
    foo(T1, T2); 
} 

C::foo(T1, T2) 
{ 
    //not using T1/T2 
} 

frente código convencional como esto

class D 
{ 
    D(); 
    ~D(); 
    bar(T1 t1, T2 t2); 
} 

D::bar(T1 t1, T2 t2) 
{ 
    //using t1 and t2 
} 

y me pregunto cuál es el propósito de no definir su tipo de variables para la usabilidad? ¿La mayoría de las personas hace esto solo para insinuar que esos parámetros de la API no están actualmente en uso, sino para garantizar la compatibilidad con versiones anteriores en el futuro?

Posiblemente sea para RTTI, o haciendo referencia a variables estáticas (aunque las diversas muestras que he visto no lo estaban usando para este propósito, ni siquiera eran funciones de plantilla, las variables simplemente no se usaban). Intenté buscar esta característica, pero ni siquiera estoy seguro de cómo se llama ni de qué buscar.

Básicamente, ¿cuáles son las razones/ventajas/desventajas para usar este enfoque?

+2

Pregunta relacionada: http://stackoverflow.com/questions/771492/c-style-convention-parameter-names-within-class-declaration – Gorpik

+1

Tal vez como una forma de hacer que el compilador no advierta de los parámetros no utilizados ... No buena idea, en mi humilde opinión, sin embargo. – dbrank0

Respuesta

9

Esto se hace comúnmente para suprimir las advertencias del compilador sobre las variables no utilizadas. Cuando no crea un nombre de variable, el compilador no le advertirá que la variable no se está utilizando en la función.

Al igual que usted declaró, por lo general su que los parámetros no están siendo utilizados para la implementación particular:

class an_iface 
{ 
public: 
    an_iface(); 

    virtual int doSomething(int valNeeded)=0; 
} 

#define NOT_SUPPORTED -1 
class something : public an_iface 
{ 
public: 
    something(); 
    int doSomething (int) { return NOT_SUPPORTED; } 
} 

class somethingMore : public an_iface 
{ 
public: 
    somethingMore(); 
    int doSomething(int stuff) { return stuff * 10; } 
} 
+0

Entonces, básicamente, ¿no hay absolutamente ninguna razón para usar esta semántica si no la está usando de forma polimórfica? Aceptaré esto si no hay otros motivos o mejores casos de uso. –

+0

No hay ninguna razón por la que se me ocurra. No tendría ningún sentido para otro propósito. Podría ser cualquier tipo de interfaz.Las señales de Qt y las ranuras vienen a la mente, donde un objeto puede emitir una señal con 2 parámetros, pero una ranura de recepción en ciertos objetos solo puede interesar a uno de ellos. – dag

+0

Respuesta aceptable entonces, dbrank0 también se refirió a la misma idea de suprimir las advertencias del compilador ... aunque estoy de acuerdo, probablemente no sea una buena idea. Tampoco hace que tu intención sea completamente clara. –

3

parámetros están diseñados antes de que los implementos en más casos que afectaron por la arquitectura más directamente

parámetros pueden estar sin usar debido a que:

  1. sobrecarga una función virtual que tiene más parámetros que se necesitan en clase derivada
  2. Existen
  3. Parámetros para la razón de la historia, y no quieren cambiar la API todavía
  4. tener en cuenta para la necesidad del futuro
+0

Muy buen segundo punto. En los grandes proyectos, no puede ir y romper la API cuando lo desee, por lo que es mejor comentar los parámetros obsoletos hasta que se programe un lanzamiento. – Thomas

5

Aparte de lo @dag ha mencionado, una definición de función sin nombre del parámetro encuentra su uso en la especialización de plantilla. Sé que ha mencionado que no hay plantillas en el ejemplo que ha publicado, pero para completar, me gustaría publicar este caso de uso:

Suponga que ha definido una función erase para los contenedores std. Pero desea erase_helper diferente para hacer el trabajo real en función del tipo de contenedor. Una práctica común y aceptable es usar traits.

// Tags for containers 
struct vector_tag {}; 
struct map_tag {}; 

// Trait class 
template <typename C> struct container_traits; 

// Specialization of trait class 
template <typename T, typename A> 
    struct container_traits<std::vector<T, A>> 
    { 
    typedef vector_tag category; 
    }; 

template <typename K, typename V, typename C, typename A> 
    struct container_traits<std::map<K, V, C, A>> 
    { 
    typedef map_tag category; 
    }; 

// Helper function 
template <typename Container, typename X> 
    void erase_helper(Container& c, const X& x, vector_tag) // <-- no param name 
    { 
    // Erase element from vector 
    } 

template <typename Container, typename X> 
    void erase_helper(Container& c, const X& x, map_tag) // <-- no param name 
    { 
    // Erase element from map 
    } 

// Function interface 
template <typename Container, typename X> 
    void erase(Container& c, const X& x) 
    { 
    erase_helper(c, x, typename container_traits<Container>::category()); 
    } 

Se puede ver aquí, tiene erase_helper tercer parámetro sin nombre. El tipo de parámetro le dice al compilador que elija la función correcta en la fase de creación de instancias de la plantilla.

+2

Para ser justos, este sigue siendo el uso polimórfico. Solo está haciendo su polimorfismo en tiempo de compilación en lugar de tiempo de ejecución. – Managu

+1

@Managu, sí lo es. Pero la pregunta original no fue para todos los casos de uso, excepto el uso polimórfico :-). – Vikas

Cuestiones relacionadas