Tiene la varianza hacia atrás.
Los tipos de devolución convierten implícitamente a tipos base (contravarianza). Pero los parámetros se convierten implícitamente en tipos derivados (covarianza) y el tipo de clase en un puntero a miembro actúa como un parámetro . Para ver esto, apliquemos el Principio de Sustituibilidad de Liskov:
El contrato de Base*
es: "Le daré una Base" (cuando usa el operador *
en mí). El contrato de Derived*
es "Le daré un derivado, que también es una base".
Claramente se puede usar Derived*
en lugar de Base*
. Por lo tanto, hay una conversión implícita de Derived*
a Base*
.
Pero considere el contrato de un puntero a miembro.
El contrato de int Base::*
es: "Dame una base y Yo te daré la espalda un int" (Un derivado es una base, por lo que aquellos son bien también) El contrato de int Derived::*
es: "Dame un derivado, y yo te devuelvo un int"(pero no cualquier edad Base
va a hacer, que debe ser un Derived
)
Imagine que tiene un Base
que no es un Derived
. Funcionará muy bien cuando elimine la referencia de un int Base::*
, pero no se puede usar con un int Derived*
).
Sin embargo, si usted tiene un
Derived
, que se puede utilizar para eliminar la referencia tanto
int Base::*
y
int Derived::*
. Por lo tanto hay una conversión implícita de
int Base::*
a
int Derived::*
Argh, hice lo que usted ha dicho y analizado el tipo que pertenece el miembro.
El LSP aún funciona. Y acepto que la conversión sea legal, al menos de acuerdo con la seguridad del tipo.El contrato es "Dame un Foo
y te daré un Derived
", que claramente puedes usar para obtener desde Foo
hasta Base
computándolo con una conversión implícita. Entonces es seguro. DeadMG probablemente esté en el camino correcto señalando la posible complicación con la ubicación de la relación del subobjeto base, especialmente en herencia virtual. Pero los punteros con los miembros tratan estos problemas en el LHS del operador de desreferencia, por lo que también podrían hacerlo por el resultado.
La respuesta final es, probablemente, simplemente que la norma no requiere que la conversión sea legal.
"La conversión de Base * a Derivado * normalmente está permitida" Creo que tiene esto al revés. –
Buena captura. Fijo. – Chris
Ver http://stackoverflow.com/questions/4295117/pointer-to-member-conversion – icecrime