2010-08-24 20 views
9

estoy de codificación en C++ y tengo algunas preguntas con respecto a los puntos suspensivos:Pasando variable número de argumentos con diverso tipo - C++

  1. ¿Es posible pasar en clase o puntero de clase en los puntos suspensivos?

  2. Básicamente lo que quiero hacer es pasar una cantidad variable de argumentos en el tipo de char* y class. Estoy usando puntos suspensivos actualmente e intentando descubrir cómo pasar la clase. Si las elipsis no son aplicables aquí, ¿cuáles son las opciones disponibles?

quiero dejar que el usuario llamar directamente a la función utilizando func(params 1, params2, ...) sin asignar explícitamente los parametros en un vector o matriz primero antes de pasar el vector o matriz como argumento de la función.

+1

me gustaría evitar los puntos suspensivos a menos que tenga para imitar la sintaxis explícita de una API existente. Prefiere encadenar o transmitir, o sobrecargas, como sugiere la respuesta de diez. – peterchen

+0

¡tenfour sugiere también usar un 'std :: vector'! –

+0

¿Cómo vas a construir un 'vector' de tipos arbitrarios, aún no conocidos? –

Respuesta

4

Puede pasar un puntero de clase con varargs, sí. Pero la función que recibe el puntero necesita saber qué hacer con ella. Tendrá que convertirlo en algo utilizable. Es por eso que printf() te hace especificar el tipo de argumento en el especificador de formato.

Una alternativa es pasar una lista a la función, como std::vector.

[editar] Es posible que se quiere hacer algo para que la sintaxis más corta, por lo que puede pasar en sus argumentos como:

foo(blah, StartAList(a)(b)(c)(d));

o arroyo-ish:

foo(blah) >> a >> b >> c >> d;

o por sobrecarga:

void foo(T a) { ... } 
void foo(T a, T b) { ... } 
void foo(T a, T b, T c) { ... } 
+0

además, IIRC el estándar (al menos pre-0x) no especifica si los objetos se pasan por valor o por referencia. ---- probablemente tendría que ser 'foo (T1, T2, T3)', también. Hicimos eso para un reemplazo 'sprintf', un PITA seguro para generar, pero ¡oh chico los errores sublimados que descubrió! Cosas que ocurren una vez en un millón, rutas de código que nunca se obtienen con pruebas automatizadas, etc. – peterchen

0

Si la instancia de clase (o puntero) se usa siempre, es mejor usar un parámetro fijo, que se pasa antes de la lista de parámetros variables, como el formato en printf. En cuanto a ... los parámetros, pueden tener cualquier tipo (incluida la instancia de clase o puntero), y su cantidad y tipos dependen de alguna convención entre un llamante y la función llamada. Por ejemplo, para printf, dicha convención se define por cadena de formato. Debe definir dicho "protocolo de comunicación", que permite usar la lista de argumentos variables. Por supuesto, esto no es seguro.

1

verdadera typesafe funciones de argumentos variables son posibles con la reciente introducción cuentan con argumentos de plantilla variables en C++ 0x

También puede obtener mediante el uso de cualquier impulso ::

+0

Está bien, pero tal caso es una plantilla varídica, y la validación se realiza en tiempo de compilación. Nada se compara con las funciones variadas completamente peligrosas. (esa es una de las razones por las que ODIO printf, mi opinión personal) –

+0

Es por eso que podría usar una nueva impresión definida basada en las plantillas variables que es segura para el tipo. http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates – David

+0

No he leído el artículo todavía, pero por el momento estoy muy contento con std :: stringstream –

17

usted debe considerar que el uso de funciones variadic (C-style) es una falla peligrosa. Si los objetos pasados ​​a la función no coinciden con el tipo esperado, o si no especifica el número exacto de parámetros esperados, básicamente tiene una caída violenta en el tiempo de ejecución.

En Bjarne Stroustrup C++ En la serie Profundidad - C++ Estándares de Codificación - 101 normas, directrices y mejores prácticas de Herb Sutter y Andrei Alexandrescu, capítulo 98: No utilice varargs (puntos suspensivos)

profundamente suscribirse a la propuesta de @tefour:

  • utilice un std::vector que contiene todos sus parámetros.
+5

Es posible que otros voten negativamente, pero este es claramente el mejor consejo en el hilo. Es muy poco probable que alguien que necesita preguntar acerca de cómo usar '...' haya pensado mucho en las implicaciones del diseño de usar '...'. –

+7

Quizás sea así, pero la necesidad de preguntar algo no significa que el programador no estará calificado para usar estas funciones para siempre. Recuerde, el programador que pregunta si algo es una buena idea es un programador que es considerado. –

10

Puede pasar lo que quiera a funciones variadas, pero esto no le ayudará a escribir funciones convenientes ya que está perdiendo la información de tipo para los argumentos.

Dependiendo de lo que quiere lograr existen mejores alternativas:

  • encadenamiento operadores como << o ():

    helper() << a << b << c; 
    helper(a)(b)(c); 
    
  • utilizando (pseudo) Plantillas variadic:

    template<class T0>   void func(T0 t0)  { ... } 
    template<class T0, class T1> void func(T0 t0, T1 t1) { ... } 
    // ... 
    
    // or if you can use C++0x features: 
    template<class... Args> void func(Args... args) { ... } 
    
  • ... más?
+0

+1 para la sobrecarga del operador. Las plantillas variables parecen mover el problema a otra parte en lugar de resolverlo. – Skizz

+1

+1 para operadores de encadenamiento – Default

+1

La clave con las plantillas variadic es que son seguras para el tipo, que es donde se encuentra el peligro en las variadicas estilo C. –

Cuestiones relacionadas