2012-02-15 6 views
19

Quiero hacer un argumento para una de las funciones miembro opcional. Cuando no se proporciona ningún argumento, usaría una variable miembro.¿Cómo usar una variable miembro como un argumento predeterminado en C++?

Sin embargo, cuando traté de compilar se muestra "error: Uso no válido de miembro de datos no estáticos 'Object' :: initPos"

Sólo para aislar el problema, he intentado incumplir un tipo int y compiló bien. Me pregunto cuál es el problema con mi código y cómo podría usar una función miembro como valor predeterminado.

¡Gracias por tu ayuda!

Object.h

class Object 
{ 
    public: 
     ... 
     void MoveTo(double speed, Point position); 

    protected: 
     Point initPos; 
     Point currPos; 

}; 

Object.c

void Object::MoveTo(double speed, Point position = initPos) 
{ 
    currPos = postion; 
} 

Point.h

class Point 
{ 
    ... 

    private: 
     double x; 
     double y; 
     double z; 
}; 
+1

Su pregunta me hizo desovar éste: http://stackoverflow.com/questions/9286801/valid-expressions-for-default-function-arguments –

Respuesta

30

Las expresiones de argumento predeterminadas para una función de miembro solo pueden depender de elementos que están en clase o alcance global. El argumento predeterminado también debe especificarse en la declaración del método (es decir, en el archivo de encabezado).

Para evitar esto, necesita 2 sobrecargas del método MoveTo. Uno que toma 1 argumento, y otro que toma 2 argumentos. El método que toma 1 argumento llama al otro método, pasando el valor que usted considera como el predeterminado.

void Object::MoveTo(double speed) 
{ 
    MoveTo(speed, initPos); 
} 

void Object::MoveTo(double speed, Point position) 
{ 
    // Everything is done here. 
} 

Tenga en cuenta que cuando se hace MoveTo(double) llamada MoveTo(double, Point), que le permite escribir la implementación de MoveTo sólo una vez, respetando así el principio DRY.

+0

¡Gracias! Sé que puedo hacerlo de esta manera. Me preguntaba si existe una forma más corta de hacerlo, como por ejemplo convertirlo en un argumento predeterminado. Pero supongo que esta sería la única forma de hacerlo. – tuzzer

+0

¿Qué pasa si, en lugar de solo un argumento opcional, tengo muchos de ellos? say void Objeto :: MoveTo (doble velocidad, posición del punto = initPos, apunte a = m_a, apunte b = m_b, apunte c = m_c) ¿entonces no tendré que hacer muchas funciones? – tuzzer

+0

@MatthewChan: Desafortunadamente, sí. En lugar de pasar muchos argumentos, quizás pueda cambiar el diseño para que el usuario pase un objeto.Este objeto ya contiene valores predeterminados razonables, y el usuario solo cambia los que deben ser diferentes. Si decides hacerlo de esta manera, es posible que te interese el modismo Method Chaining para hacer que establecer múltiples parámetros sea más conciso (http://en.wikipedia.org/wiki/Method_chaining). –

10

valores predeterminados no son parte del prototipo, es decir, que estamos resueltos por el llamador, no por la función en sí. Entonces, en primer lugar, deben ser visibles para quien llama. En segundo lugar, no pueden acceder a los miembros protegidos de la clase. (Estoy bastante seguro de que ni siquiera puedes usar miembros públicos como valores predeterminados, pero estoy demasiado cansada para comprobarlo)

Para resolver el problema, utiliza sobrecargas encadenadas como se sugiere en otras respuestas.

+0

Gracias. Traté de cambiar initPos a público, pero como dijiste, todavía no funcionará. ¿Entonces es que solo podemos usar constante como argumento predeterminado (como la función no miembro, algo que puede escribir)? – tuzzer

1

Puede sobrecargar el miembro de su función como esa:

void Object::MoveTo(double speed, Point position) { 
    .... 
} 

void Object::MoveTo(double speed) { 
    Point position = this->initPos; 

    MoveTo(speed, position); 
} 
+0

desafortunadamente, el único trabajo que podría hacer el trabajo, aunque parece feo :( – Argento

Cuestiones relacionadas