2011-11-24 24 views
8

Tengo que escribir el constructor con dos parámetros predeterminados.cómo saltear Argumentos predeterminados C++?

func(int arg1 , char* arg2 = "arg2", int arg3 = 1) //example 

me proporciona el escenario en el que se llama al constructor y se le da un valor a arg1 y arg2 y arg3 se espera que utilice un valor predeterminado. A continuación, se crea una instancia de otro objeto y se da un valor a arg1 y arg3, y se espera que se use el valor predeterminado para arg2. Ahora el problema es que "no se puede omitir" los parámetros predeterminados es lo que estoy leyendo del texto y en línea. Se dice ordenar los parámetros predeterminados por su simpatía de sobrecarga, pero el escenario tiene un parámetro predeterminado utilizado mientras que el otro no. Las sugerencias para esta pregunta me dicen que reordene los parámetros/argumentos. Sin embargo, ninguna cantidad de reordenamiento que he hecho parece ser capaz de resolver este problema.

Además, los constructores sobrecargados no se pueden utilizar. Esto tiene que ser hecho por un constructor.

¿Cómo podría uno hacer esto? Estoy perplejo e ir un poco loco sobre este :(

+6

No puede hacer esto en C++ con una sola definición de función. Dado que cualquier otra solución viola las limitaciones extrañas que tiene, lo que quiere es imposible. Quizás puedas usar un idioma diferente. –

+1

es esta tarea? – xmoex

+0

¿No podría usar un 'vector' de' objeto? De esta forma, podría pasar lo que desea y ordenar lo que no se aprobó según las entradas 'null'. – MoonKnight

Respuesta

6

Además, constructores sobrecargados no se pueden utilizar. Esto tiene que ser hecho por un constructor.

La única razón que se me ocurre para este requisito es que los argumentos opcionales tienen el mismo tipo. En ese caso, está atascado y querrá consultar las expresiones idiomáticas named constructor y/o named parameter.

De lo contrario, simplemente defina el constructor adicional. puede implicar cierta duplicación de los valores predeterminados.

Foo(int arg1 , char const *arg2 = "arg2", int arg3 = 1) 
{ 
    construct(arg1, arg2, arg3); 
} 

Foo(int arg1, int arg3) 
{ 
    construct(arg1, "arg2", arg3); 
} 
+1

Esos son algunos modismos muy agradables, gracias por compartir los enlaces. Una de las cosas increíbles sobre Stack Overflow es que puedes leer detenidamente los hilos y aprender algunas cosas geniales :) +1 –

0

Restricción peculiar, que debe haber un solo constructor. Aquí está el más cercano que puedo pensar:

#include <iostream> 

// cheap and cheerful Boost.Variant 
struct StringOrInt { 
    char *s; 
    int i; 
    bool is_string; 
    StringOrInt(char *s) : s(s), i(0), is_string(true) {} 
    StringOrInt(int i) : s(0), i(i), is_string(false) {} 
    bool isInt() { return !is_string; } 
    int asInt() { return i; } 
    char *asString() { return s; } 
}; 

struct Foo { 
    int m1; 
    char *m2; 
    int m3; 
    Foo(int arg1, StringOrInt arg2 = "arg2", int arg3 = 1) : m1(arg1) { 
     if (arg2.isInt()) { 
      arg3 = arg2.asInt(); 
      arg2 = "arg2"; 
     } 
     m2 = arg2.asString(); 
     m3 = arg3; 
    } 
    void print() { 
     std::cout << m1 << " " << m2 << " " << m3 << "\n"; 
    } 
}; 

int main() { 
    Foo(1, "HelloWorld").print(); 
    Foo(1, 2).print(); 
} 

Tenga en cuenta que con GCC esto genera advertencias, ya que la conversión de una cadena literal que no constante char* es obsoleto y poco inteligente. Pero es lo que solicitó y lo corrigió para que los parámetros char* y el miembro de datos sean const char*.

Una debilidad importante es que esto no le impide escribir Foo(1,2,3). Para comprobar que en tiempo de compilación creo que necesita múltiples constructores. Para verificarlo en tiempo de ejecución, puede convertir el tercer parámetro en otra clase, DefaultOrInt, donde Default es un tipo utilizado solo para este propósito, que admite solo un valor utilizado como valor predeterminado de arg3. Entonces, si arg2.isInt() es verdadero, marque arg3.isInt() como falso y si no arroje logic_error.

0

Si se le permite pasar un C-string vacío cuando no tiene ningún valor para el segundo parámetro, puede usar un funcionador de ayuda que marcará arg2 y devolverá el valor predeterminado si está vacío. Algo como esto:

#define DEFAULT_ARG "arg2" 

struct helper_class { 
    char* operator()(char* arg) 
    { 
     if (*arg) return arg; else return DEFAULT_ARG; 
    } 
} helper; 

class func { 
    public: 
    func(int arg1 , char* arg2 = "arg2", int arg3 = 1) {} 
}; 

int main() 
{ 
    func f1(42, helper(""), 9001); // default 2nd argument 
    func f2(42, helper("Its over 9000!")); 
} 

No es bonita, lo sé ...

0

En este momento se puede utilizar std::bind a hacer este tipo de operación o en C++ 14/17 puede utilizar la función lambda y lograr lo mismo.

Cuestiones relacionadas