c++ - prioridad - (implica explícita) Precedencia con conversión de operador y constructor
precedencia de operadores en programacion (1)
Una muy buena pregunta.
En primer lugar, lo explicit
no significa que "esto tiene prioridad si se requiere una conversión explícita". Significa que "esto solo se puede invocar explícitamente". Por lo tanto, crea algunas situaciones en las que no se puede invocar, no obliga a invocarlo en otras situaciones.
Otra cosa a considerar es que static_cast
es la inicialización directa , mientras que pasar un argumento a una función es la inicialización de la copia . Entre otras cosas, la inicialización de copia nunca usa constructores explícitos. Otra cosa a tener en cuenta es que la inicialización directa requiere el uso de constructores para las clases (explícito o no). Aunque eso no significa que una conversión no pueda realizar la inicialización directa: se puede usar para convertir el argumento de un constructor y si el constructor es una copia generada por el compilador, entonces parecería que la función de conversión realizó la inicialización directa (mientras que de hecho fue realizado por el constructor de copia). Intente declarar un constructor de copia sin definirlo (la técnica de desactivación de copia) y verá que la función de conversión ya no funciona en el contexto de inicialización directa: compilará, pero causará un error de vinculación.
Con eso en mente:
- Obvio.
- La inicialización directa requiere un constructor, por lo que se invoca.
- Obvio.
- Lo mismo que 2, realmente. Declarar
explicit
función de conversión impide que se invoque implícitamente, no obliga su uso en contextos explícitos. - Obvio.
- De nuevo, la inicialización directa requiere un constructor y permite el uso de los explícitos.
- Obvio.
- Otro caso de inicialización directa.
He navegado a través de una gran cantidad de preguntas relacionadas con la conversión, pero parecía que ninguno de ellos discutía sobre palabras clave explícitas de esta manera. Aquí está el código:
struct B;
struct A{
/*explicit*/ A(const B&){ cout << 1; } // *1
};
struct B{
/*explicit*/ operator A()const{ cout << 2; } // *2
};
void foo(const A &){}
int main(void){
B b;
foo( /*static_cast<A>*/ (b) ); // *3
}
Resultado: (S: sin comentar, N: comentado, X: cualquiera)
# | *1 | *2 | *3 |output|
1 | N | N | N |error |
2 | N | N | Y | 1 |
3 | N | Y | N | 1 |
4 | N | Y | Y | 1 |
5 | Y | N | N | 2 |
6 | Y | N | Y | 1 |
7 | Y | Y | N |error |
8 | Y | Y | Y | 1 |
1, 7 son errores, lo cual es normal. (Ambiguo y sin conversión automática)
2 parece que el constructor tiene mayor precedencia, pero ¿por qué?
3, 5 son fáciles de entender.
4 es extraño ya que no llama al explícito. ¿por qué?
6 puede ser debido a que ''explícito'' o constructor tiene mayor precedencia. ¿Cuál es la razón? 8 parece que el constructor tiene mayor precedencia, pero ¿por qué?
¿Podría alguien ofrecer algunas explicaciones? ¡Gracias!