2010-10-24 23 views
15

Si lo siguiente de C++ FAQ Lite es verdadero: "el nombre de una función decae a un puntero a la función" (como un nombre de matriz decae a un puntero a su primer elemento); ¿Por qué tenemos que incluir el ampersand?Puntero de función de miembro

typedef int (Fred::*FredMemFn)(char x, float y); 
FredMemFn p = &Fred::f; 

Y no sólo:

typedef int (Fred::*FredMemFn)(char x, float y); 
FredMemFn p = Fred::f; 

En el segundo caso Fred :: f es una función y puede decaer a un puntero a esa función.

Espero que esta pregunta no sea tan estúpida.

+0

My guess! Sería ambiguo, porque 'Fred :: f' también puede significar una variable estática en la clase. – AraK

+1

+1 para una pregunta no estúpida – fredoverflow

+0

@FredOverflow: gracias;) –

Respuesta

16

Respuesta original:

debido a una función miembro no es una función y una función triple miembro no es una función triple. Por lo tanto, las reglas de decaimiento no se aplican.

Además, existe el tipo de función en C++, pero no el tipo de función de miembro. De modo que puede usar una función en lugares donde se espera un puntero a función, pero no puede usar una función de miembro porque no existe tal cosa, solo la función de puntero a miembro. f en tu ejemplo es una función. Por otro lado, Fred :: f es ... bueno, nada.

Además, yo diría que "el nombre de una función puede decaer ...". No, el nombre no se puede hacer nada, un valor-I de tipo de función se puede convertir implícitamente a una función puntero a, y esto es una conversión de identidad en cuanto a la resolución de sobrecarga se refiere

Edición aclarar mi respuesta:

Cada expresión en C++ tiene un tipo y un valor. Un valor de un tipo puede ocasionalmente convertirse a un valor de otro tipo. Estas conversiones se clasifican de manera que para hacer una conversión mejor que otra, principalmente para la resolución de sobrecarga de función.

Uno de los tipos de conversiones se llama conversión lvalue-a-rvalue. Cuando aparece un valor l en un contexto donde se requiere un valor r, esta conversión se lleva a cabo. Por lo general, este tipo de conversión no hace nada, por ejemplo:

int i = 4, j = 5; 
i = j; 

en la segunda línea j es un valor-I, pero se necesita un rvalue aquí, así que j se convierte en un valor de lado derecho. Pero esta no es una conversión observable, ¿verdad? Pero hay casos en los que se puede observar la conversión lvalue-r-value. Es decir, un lvalue de matriz de n T se puede convertir en un valor p de tipo T* cuyo valor es la dirección del primer elemento de la matriz y un lvalue de tipo "función con la firma S" un rvalue del tipo "puntero a función con la firma S" cuyo valor es la dirección de la función

eso significa que cuando asignamos una función a una función de puntero a la función lvalue está implícitamente convirtió en su dirección.

void f() {} 
void (*p)() = f; //f is converted to rvalue 

f es una expresión y tiene un tipo.tipo de f es void()

No hay tal tipo en C++ como un member-function Hay punteros a miembro-funciones, pero no las funciones miembros. Estoy hablando, por supuesto, de funciones no estáticas. Las funciones estáticas funcionan de la misma manera que las funciones normales, es decir, no es necesario escribir &X::f, sino que puede escribir X::f ¿Por qué? Porque X :: f tiene una función de tipo y se lleva a cabo la conversión mencionada. Si f no es estático, sin embargo, X :: f es de tipo ... ¿qué? Ah, sí, no tiene un tipo y, por lo tanto, no es una expresión y, por lo tanto, no tiene valor y, por lo tanto, ese valor no se puede convertir en nada.

Cita del estándar: 5.3.1 cláusula 3 Un puntero al miembro solo se forma cuando se usa un & explícito y su operando es un id. Calificado no encerrado entre paréntesis. [Nota: es decir, la expresión & (id-calificado), donde el id-calificado está entre paréntesis, no forma una expresión de tipo "puntero al miembro". Tampoco lo hace id-calificado, porque no hay conversión implícita desde un id calificado para una función de miembro no estático al tipo "puntero a función de miembro", ya que existe desde un valor l de tipo de función al tipo "puntero a función" (4.3). Tampoco es & sin id-id un puntero al miembro, incluso dentro del alcance de la clase de id no calificado. ]

Espero que esto haya sido más claro ...

+0

"Hay un tipo de función en C++, pero no un tipo de función de miembro". -> ¿Qué quieres decir exactamente con eso? Seguramente 'FredMemFn' tiene un tipo? – fredoverflow

+0

@FredOverflow: Sí, FredMemFn tiene un tipo y ese tipo es "puntero a miembro, incluida la clase y de qué firma". Cada expresión en C++ tiene un tipo. Por ejemplo, si f es una función independiente void f(), el tipo de la expresión (f) es void() que es un tipo de función. Por otro lado, la expresión Fred :: f no es una expresión porque no tiene un tipo. Pero & Fred :: f es una expresión de tipo puntero-a-miembro blah blah ... eso es lo que quiero decir –

+0

¿El operador '&' no requiere una expresión como su operando? – fredoverflow

Cuestiones relacionadas