2012-04-23 7 views
6

Estoy tratando de tener una clase que permita la conversión implícita a ciertos tipos incorporados, como unsigned long int y porque estoy tratando de hacerlo lo más correcto posible (este es mi primer proyecto importante en C++), he golpeado una edición extraña con respecto a la corrección const:C++ Overloading Conversion Operators

esto funciona:

#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt(); 
    CustomizedInt(int input); 
    operator unsigned long int() const 
    { 
     unsigned long int output; 
     output = (unsigned long int)data; 
     return output; 
    } 
}; 

CustomizedInt::CustomizedInt() 
{ 
    this->data = 0; 
} 

CustomizedInt::CustomizedInt(int input) 
{ 
    this->data = input; 
} 

int main() 
{ 
    CustomizedInt x; 
    unsigned long int y = x; 

    std::cout << y << std::endl; 

    return 0; 
} 

Pero esto:

#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt(); 
    CustomizedInt(int input); 
    operator unsigned long int() const; 
}; 

CustomizedInt::CustomizedInt() 
{ 
    this->data = 0; 
} 

CustomizedInt::CustomizedInt(int input) 
{ 
    this->data = input; 
} 

CustomizedInt::operator unsigned long() 
{ 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 

int main() 
{ 
    CustomizedInt x; 
    unsigned long int y = x; 

    std::cout << y << std::endl; 

    return 0; 
} 

me da este error en Visual Studio 2010: error C2511: 'CustomizedInt::operator unsigned long(void)' : overloaded member function not found in 'CustomizedInt'

Ahora, si elimino la palabra clave const de la definición del operador, todo está bien. ¿Es esto un error? Leí que se supone que debo usar la palabra clave const después de cada método/operador (público) para indicar claramente que no altera el objeto actual de ninguna manera.

Además, sé que la definición de dicho operador puede ser una mala práctica, pero no estoy seguro de entender completamente las advertencias asociadas. ¿Alguien podría describirlos? ¿Sería mejor práctica definir un método público llamado ToUnsignedLongInt?

Respuesta

8

La función de firma no coincide con la definición de la función.

operator unsigned long int() const; 

y

CustomizedInt::operator unsigned long() { ... } 
             ^^^ 
            const missing 

En este caso, deberá marcar el operador de conversión como const ya que no afecta el estado interno del objeto.

Además, use las listas de inicialización del constructor para inicializar sus variables miembro.

CustomizedInt::CustomizedInt() 
: data() 
{ 
} 

CustomizedInt::CustomizedInt(int input) 
: data(input) 
{ 
} 
+0

¡Sí, gracias! Por alguna razón, pensé que no era necesario repetir el const postpendido en la implementación ...En cuanto a los constructores, sí, las listas de inicialización son útiles, pero, en mi implementación real, los datos tienen un tipo complejo, y la implementación del constructor es demasiado compleja para las listas de inicialización ... –

+0

@MihaiTodor If 'data' tiene un tipo complejo Yo diría que esa es una razón más para usar una lista de inicialización en lugar de una asignación. Las [Preguntas frecuentes sobre C++] (http://www.parashift.com/c++faq-lite/ctors.html#faq-10.6) explican por qué es una buena práctica y también enumera algunas excepciones a esta regla. – Praetorian

+0

Bueno, estoy completamente de acuerdo, pero ¿qué haces si necesitas llamar a ciertas funciones para inicializar esa información? Estoy usando la biblioteca GMP y los datos son del tipo mpz_t, que deben inicializarse con mpz_init (...). ¿Cómo puedo llamar a la función mpz_init en los datos en la lista de inicialización? –

2

Sí, si su función de miembro no afecta el estado lógico del objeto, entonces debe postfreccionarlo con const, por lo que el compilador aplicará eso.

Pero en ese caso, también debe agregar const cuando defina el cuerpo de la función.

+0

Hm ... ¡Funciona! Por alguna razón, no funcionó antes, pero creo que debo haber cometido otro error en alguna parte ... Muchas gracias :) –

6

Usted podría retire la const de la declaración, pero lo que es casi seguro que quiere hacer es añadir a la definición:

CustomizedInt::operator unsigned long() const 
{ 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 
+0

Bueno, pero ¿y si la implementación de este operador es más grande que mi simple ejemplo? No quiero agregar 10 líneas de código de implementación en el encabezado, por lo que quiero implementarlo fuera de la clase ... –

+0

@ michael85: deje el encabezado tal como está. Simplemente agregue el 'const' donde lo implementa. Las dos firmas necesitan coincidir. –

+0

Sí, lo tengo. Gracias. –

1

Solo tiene que copiar el mismo prototipo de función en la implementación. es decir.

CustomizedInt::operator unsigned long int() const 
+0

Yeap ... Gracias :) –