2009-07-13 12 views
5

¿Hay alguna diferencia entre el puntero a const y el puntero habitual para las funciones? ¿Cuándo es adecuado usar el calificador const para funciones independientes?puntero a const frente al puntero habitual (para funciones)

escribí pequeña muestra para ilustrar mi pregunta:

#include <iostream> 
using namespace std; 

int sum(int x, int y) { return x + y; } 
typedef int sum_func(int, int); 

int main() 
{ 
    const sum_func* sum_func_cptr = &sum; // const function 
    sum_func* sum_func_ptr = &sum;  // non-const function ? 

    // What is the difference between sum_func_cptr and sum_func_ptr 

    int x = sum_func_cptr(2, 2); 
    cout << x << endl; 

    int y = sum_func_ptr(2, 2); 
    cout << y << endl; 

    sum_func_cptr = 0; 
    sum_func_ptr = 0; 

    return 0; 
}

g ++ da ninguna advertencia. Es por eso que pregunto.

Respuesta

12

su código es mal formados con respecto a C++ 03. Puede no construir alguna vez un tipo de función calificada const (o volátil). Cada vez que lo haces, tu programa se vuelve mal formado.

Esta regla has been changed para C++ 1x, para hacer que el compilador ignore el const/volatile. Los compiladores de C++ generalmente ya implementarán esta regla incluso en el modo C++ 03. Por lo tanto, los siguientes dos definirán la misma función dos veces, y dará como resultado un error de compilación.

typedef void Ft(); 


void f(Ft const*) { } 
void f(Ft *) { } // another definition! 

Aquí está la prueba de mi reclamo. C++ 03, 8.3.5/1

Un CV-calificador-seq sólo será parte del tipo de función para una función miembro no estático, el tipo de función a la que un puntero a miembro se refiere, o el tipo de función de nivel superior de una función typedef declaration. El efecto de un cv-qualifier-seq en un declarador de función no es lo mismo que agregar cv-qualification sobre el tipo de función, es decir, no crea un tipo de función cv-qualified. De hecho, si en algún momento en la determinación de un tipo se forma un tipo de función calificada como cv, el programa está mal formado.

aquí es que el texto para C++ 1x, 8.3.5/7 n2914:

A fi er-seq cv-cuali sólo será parte del tipo de función para una función miembro no estático, el tipo de función a lo que se refiere un puntero al miembro, o el tipo de función de nivel superior de una declaración de función typedef. El efecto de un cv-quali fi er-seq en un declarador de funciones no es lo mismo que agregar cv-quali fi cation en la parte superior del tipo de función. En este último caso, los calificadores cv son ignorados.

Lo anterior dice que lo que sigue es válido, sin embargo, y crea el tipo de función para una función que puede declarar una función de miembro constante.

typedef void Ft() const; 
struct X { Ft cMemFn; }; 
void X::cMemFn() const { } 
+0

Oye, está el experto de Standard del que estaba hablando. : P – GManNickG

+0

Hehe, soy te n00b con textos estándar. Pero me alegro de que te guste el análisis :) –

+0

He leído C++ 98 estándar. Es por eso que no pude encontrarlo. –

1

Creo que significó,
sum_func* const sum_func_cptr en lugar de const sum_func* sum_func_cptr.

sum_func* const sum_func_cptr = &sum; 
sum_func* const sum_func_cptr = &sum_new; // will not compile. 
// whereas, 
const sum_func* sum_func_cptr = &sum; // will compile 
const sum_func* sum_func_cptr = &sum_new; // will compile. 
sum_func* sum_func_cptr = &sum; // will compile 
sum_func* sum_func_cptr = &sum_new; // will compile. 

-Jagannath.

+0

No. Me refería exactamente a lo que escribí. –

+1

@ jia3ep: Luego escribiste mal el título y la descripción. "const pointer to X" significa "X * const"; mientras que "puntero a const X" significa "const X *". Deberías hacerlo bien primero. – newacct

+0

He corregido el título y la descripción. –

6

Las funciones autónomas son const por definición. Por lo tanto, no hay diferencia entre un puntero de función const y uno const.

+0

¿Hay alguna información en el estándar que diga ignorar calificador para funciones independientes? No puedo encontrar –

+0

No sé si hay algo en el estándar para esto. – Naveen

+0

Hice lo mejor que pude en mi respuesta, pero creo que hay algo mejor, como decir explícitamente que 'las funciones son const'. – GManNickG

0

Como un aspecto interesante, el especificador const no parece tener un efecto incluso cuando se utiliza en punteros a las funciones miembro.

#include <iostream> 
using namespace std; 

class Foo { 
public: 
    int sum(int x, int y) { 
    _x = x; 
    _y = y; 
    return x + y; 
    } 
private: 
    int _x; 
    int _y; 
}; 

typedef int (Foo::*sum_func)(int,int); 

int main() 
{ 
    Foo f; 
    const sum_func sum_func_cptr = &Foo::sum; // const pointer 
    sum_func sum_func_ptr = &Foo::sum;  // non-const pointer 

    int x = (f.*sum_func_cptr)(2, 2); 
    cout << x << endl; 

    int y = (f.*sum_func_ptr)(2, 2); 
    cout << y << endl; 

    const sum_func* sum_func_cptr_cptr = &sum_func_cptr; 
    sum_func* sum_func_ptr_ptr = &sum_func_ptr; 

    x = (f.**sum_func_cptr_cptr)(2, 2); 
    cout << x << endl; 

    y = (f.**sum_func_ptr_ptr)(2, 2); 
    cout << y << endl; 

    return 0; 
} 
0

Creo que ha habido un malentendido básico en las respuestas anteriores.

const sum_func sum_func_cptr = &Foo::sum; // const pointer 

Eso significa que sum_func_cptr es un puntero a una función constante, es decir se puede inicializar con una función miembro no constante, pero no se puede cambiar más adelante para apuntar a otra función, ya que se refiere const a la variable. Eso es equivalente a:

sum_func const sum_func_cptr = &Foo::sum; // const pointer 

¿no le parece? :-)

-Paolo

+0

no hay tipos de funciones const. entonces 'const sum_func stuff = & Foo :: sum;' no tiene sentido, como dice la cita del estándar en mi respuesta. Tampoco sería válido decir 'sum_func * const sum_func_cptr = & Foo :: sum;' (* this * es un puntero de función const), porque intenta asignar un puntero de función miembro a un puntero de función. Tendría que hacer 'sum_func Foo :: * const sum_func_cptr = & Foo :: sum;'. –

+0

Tomé la publicación anterior como un ejemplo. Define el nuevo tipo "sum_func" como una función de puntero a miembro: typedef int (Foo :: * sum_func) (int, int); Mi punto era que "const" agregado a "sum_func" no lo cambia a "pointer-to-const-member-function". Francamente, ni siquiera sé ho escribir ese typedef. Y no sabía que podía definir tipos de funciones solo, solo punteros a funciones. – Paolo

Cuestiones relacionadas