tipos programas lenguaje ejemplos datos conversion completo comandos basico c++ conversion-operator

programas - manual completo de c++ pdf



Operadores de conversiones en C++ (4)

Por favor, ayúdame a entender cómo funcionan exactamente los operadores de conversión en C ++. Aquí tengo un ejemplo simple que estoy tratando de entender, aunque no está muy claro cómo la compilación realmente realiza la conversión.

class Example{ public: Example(); Example(int val); operator unsigned int(); ~Example(){} private: int itsVal; }; Example::Example():itsVal(0){} Example::Example(int val):itsVal(val){} Example::operator unsigned int (){ return (itsVal); } int main(){ int theInt = 5; Example exObject = theInt; // here Example ctr(5); int theInt1 = ctr; // here return 0; }


Puede recorrer ese código con un depurador (y / o poner un punto de interrupción en cada uno de sus constructores y operadores) para ver cuál de sus constructores y operadores está siendo invocado por qué líneas.

Como no los definió explícitamente, el compilador también creó un constructor de copia oculta / predeterminado y un operador de asignación para su clase. Puede definirlos explícitamente (de la siguiente manera) si desea usar un depurador para ver dónde / cuándo se están llamando.

Example::Example(const Example& rhs) : itsVal(rhs.itsVal) {} Example& operator=(const Example& rhs) { if (this != &rhs) { this->itsVal = rhs.itsVal; } return *this; }


Example exObject = theInt; // here

Esto utiliza la conversión implícita de int a Example, efectuada por el constructor no explícito que acepta un int.

Esto también requiere la disponibilidad de un constructor de copia para el Ejemplo, aunque el compilador puede omitir la copia de la instancia.

int theInt1 = ctr; // here

Esto utiliza la conversión implícita de Example a unsigned int, proporcionada por el operador de conversión.

Los operadores de conversión normalmente se evitan, ya que tienden a generar códigos confusos, y puede marcar explícitamente los constructores de un solo argumento para deshabilitar las conversiones implícitas a su tipo de clase. C ++ 0x también debería agregar la posibilidad de marcar operadores de conversión explícitos (¿por lo que necesitaría un static_cast para invocarlos? Mi compilador no los admite y todos los recursos web parecen concentrarse en la conversión explícita a bool).


Example exObject = theInt; // implicitly created copy constructor takes place // object implicitly created from int and then copied // it is like Example exObject = Example(theInt); // so it uses sequence // Example(int) -> Example(const Example&) int theInt1 = ctr; // operator int()

Si el compilador admite la optimización del constructor de copias y la optimización del valor de retorno, no lo notará

Example(const Example&)

ejecución, pero puede declarar que el constructor de copias es privado para entender de qué estoy hablando.


int main() { int theInt = 5; /** * Constructor "Example(int val)" in effect at the statement below. * Same as "Example exObject(theInt);" or "Example exObject = Example(theInt);" */ Example exObject = theInt; // 1 Example ctr(5); /** * "operator unsigned int()" in effect at the statement below. * What gets assigned is the value returned by "operator unsigned int()". */ int theInt1 = ctr; // 2 return 0; }

En la declaración 1 se llama al constructor Example(int val) . Declárelo como explicit Example(int val) y obtendrá un error de tiempo de compilación, es decir, no se permitirá ninguna conversión implícita para este constructor.

Todos los constructores de argumentos individuales se llaman implícitamente si el valor asignado es de su tipo de argumento respectivo. El uso de la palabra clave explicit antes de los constructores de un solo argumento deshabilita la llamada implícita del constructor y, por tanto, la conversión implícita.

Si el constructor se declarara como explícito, es decir, explicit Example(int val) entonces sucedería lo siguiente para cada declaración.

Example exObject(theInt); // Compile time error. Example exObject = theInt; // Compile time error. Example exObject(Example(theInt)); // Okay! Example exObject = Example(theInt); // Okay!

También tenga en cuenta que en el caso de una llamada implícita al constructor y, por lo tanto, una conversión implícita, el valor asignado es un valor r, es decir, un objeto sin nombre creado implícitamente mediante un valor l (theInt) que nos dice que en el caso de una conversión implícita el compilador convierte

Example exObject = theInt;

a

Example exObject = Example(theInt);

Por lo tanto (en C ++ 11) no espere que se llame al constructor lvalue al ver que está usando un lvalue, es decir, un valor con nombre theInt para la asignación. Lo que se llama es el constructor rvalue ya que el valor asignado es en realidad el objeto sin nombre creado usando el lvalue. Sin embargo, esto se aplica si tiene las versiones lvalue y rvalue del constructor.

En la instrucción 2 se llama al operator unsigned int() . Simplemente considérelo como una llamada de función normal con un nombre extraño y el hecho de que se puede llamar automáticamente cuando ocurre una conversión implícita. El valor devuelto por esa función es el valor asignado en la expresión. Y como en su implementación el valor devuelto es un int, se asigna correctamente a int theInt1 .

Para ser preciso operator unsigned int() overloads () operador que es el operador de yeso. En su caso, está sobrecargado para int por lo tanto, cada vez que se asigna un objeto de la clase Example a un int la conversión implícita del tipo de Example a int y, por lo tanto operator unsigned int() se llama al operator unsigned int() . Por lo tanto,

int theInt1 = ctr;

es equivalente a

int theInt1 = (int)ctr;