Acabo de encontrar los siguientes párrafos en el borrador estándar de C++ 03 relevantes para la conversión de puntero a miembro.Conversión de puntero a miembro
4,11/2 Puntero a conversiones miembro
Un valor p de tipo “puntero a miembro de B de tipo cv T”, donde B es un tipo de clase, se puede convertir en un valor p de tipo "Puntero al miembro de D de tipo cv T", donde D es una clase derivada (cláusula 10) de B. Si B es una clase base inaccesible (cláusula 11), ambigua (10.2) o virtual (10.1) de D, una el programa que necesita esta conversión está mal formado. El resultado de la conversión hace referencia al mismo miembro que el puntero al miembro antes de que tuviera lugar la conversión, pero se refiere al miembro de la clase base como si fuera miembro de la clase derivada. El resultado se refiere al miembro en la instancia D de B. Dado que el resultado tiene el tipo "puntero a miembro de D de tipo cv T", puede desreferenciarse con un objeto D. El resultado es el mismo que si el puntero al miembro de B se elimina la referencia con el B sub-objeto de D. El valor de puntero nulo miembro se convierte en el valor del puntero miembro nula de la type.52 destino)
5.2.9/9 static_cast
un valor p de tipo “puntero a miembro de D de tipo CV1 T” puede ser convertido a un valor p de tipo “puntero a miembro de B de tipo cv2 T”, donde B es una clase base (cláusula 10) de D, si existe una conversión estándar válida de "apuntador a miembro de B de tipo T" a "apuntador a miembro de D de tipo T" (4.11), y cv2 es el mismo CV -calificación como, o mayor calificación cv que, cv1.63) El valor del puntero del miembro nulo (4.11) se convierte al valor del puntero del miembro nulo del tipo de destino. Si la clase B contiene el miembro original, o es una clase base o derivada de la clase que contiene el miembro original, el puntero resultante al miembro apunta al miembro original. De lo contrario, el resultado del lanzamiento no está definido. [Nota: aunque la clase B necesita no contiene el miembro original, el tipo dinámico del objeto sobre el que se quita la referencia al miembro debe contener el miembro original; ver 5.5. ]
Así que aquí está mi pregunta. Como dice 5.2.9/9, un puntero al miembro de D se puede convertir en un puntero al miembro de B, si existe una conversión válida descrita en 4.11/2. ¿Significa esto que si hay un miembro 'm' de D que no se hereda de B, el puntero al miembro 'm' no se puede convertir al tipo de puntero al miembro de B?
class Base { };
class Derived : public Base
{
int a;
};
typedef int Base::* BaseMemPtr;
BaseMemPtr pa = static_cast<BaseMemPtr>(&Derived::a); // invalid, as per 5.2.9/9 ?
En la nota de 5.2.9/9, también dice que a pesar de la clase B no tiene por qué contener el miembro original, el tipo dinámico del objeto sobre el que se eliminan las referencias del puntero a miembro debe contener el miembro original .
Me confunden con la redacción del párrafo. ¿Es válido el código anterior?
He buscado en el sitio, y hay una pregunta similar, c++ inheritance and member function pointers, cuya respuesta solo cubría el caso de la conversión de puntero a miembro de la clase base a puntero a miembro de la clase derivada.
Está asignando un puntero al valor del miembro de datos a un puntero a la variable de función del miembro. De lo contrario, sí, "el resultado del lanzamiento no está definido". – Potatoswatter
Gracias, lo arreglé. – ashen