2009-07-13 3 views
5

C'è qualche differenza tra puntatore a const e puntatore normale per le funzioni? Quando è opportuno utilizzare il qualificatore const per le funzioni autonome?puntatore a const vs puntatore solito (per funzioni)

ho scritto breve esempio per illustrare la mia domanda:

#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 ++ dà nessun avviso. Ecco perché chiedo.

risposta

12

il codice è mal formate per quanto riguarda C++ 03. È possibile non mai costruire un tipo di funzione qualificato const (o volatile). Ogni volta che lo fai, il tuo programma diventa mal formato.

Questa regola has been changed per C++ 1x, per fare in modo che il compilatore ignori lo const/volatile. I compilatori C++ di solito implementano già questa regola anche in modalità C++ 03. Pertanto, i due seguenti definiranno la stessa funzione due volte e genereranno un errore di compilazione.

typedef void Ft(); 


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

Ecco la prova della mia richiesta. C++ 03, 8.3.5/1

A cv-qualificazione-seq è solo una parte del tipo di funzione per una funzione membro non statica, il tipo di funzione a cui un puntatore a membro riferisce, o il tipo di funzione di primo livello di una funzione typedef declaration. L'effetto di un qualificatore-cv-seq in un dichiaratore di funzione non è lo stesso di aggiungere qualifica cv al di sopra del tipo di funzione, cioè non crea un tipo di funzione qualificata cv. Infatti, se in qualsiasi momento nella determinazione di un tipo viene formato un tipo di funzione qualificata cv, il programma è mal formato.

Ecco quello testo per C++ 1x, 8.3.5/7 n2914:

A fi er-seq cv-quali è solo una parte del tipo di funzione per una funzione membro non statica, il tipo di funzione a cui fa riferimento un puntatore al membro o il tipo di funzione di livello superiore di una dichiarazione typedef di una funzione. L'e ff etto di un cv-quali fi se-seq in un dichiaratore di funzioni non è lo stesso di aggiungere cv-quali fi cazione in cima al tipo di funzione. In quest'ultimo caso, i cv-quali fi sono ignorati.

Quanto sopra dice che il sotto è valido, però, e crea il tipo di funzione per una funzione che può dichiarare una funzione membro const.

+0

Ehi, c'è l'esperto di Standard di cui stavo parlando. : P – GManNickG

+0

Hehe, sono te n00b con testi standard. Ma sono contento che ti piaccia l'analisi :) –

+0

Ho letto C++ 98 standard. Ecco perché non sono riuscito a trovarlo. –

1

Penso che intendessi,
sum_func* const sum_func_cptr anziché 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. Intendevo esattamente quello che ho scritto. –

+1

@ jia3ep: Quindi hai scritto il tuo titolo e la descrizione sbagliata. "const puntatore a X" significa "X * const"; mentre "puntatore a const X" significa "const X *". Dovresti farlo bene prima. – newacct

+0

Ho corretto titolo e descrizione. –

6

Le funzioni stand alone sono const per definizione. Quindi non vi è alcuna differenza tra un puntatore const e un puntatore non const.

+0

C'è qualche informazione in Standard che dice di ignorare il qualificatore per le funzioni autonome. Non riesco a trovarlo –

+0

Non sono a conoscenza se c'è qualcosa nello standard per questo. – Naveen

+0

Ho fatto del mio meglio nella mia risposta ma sento che c'è qualcosa di meglio, come se affermasse esplicitamente che 'function are const'. – GManNickG

0

Come interessante, il costitatore const non sembra avere un effetto anche se utilizzato sui puntatori alle funzioni membro .

#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

Penso che ci sia stato un malinteso fondamentale nelle risposte precedenti.

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

Ciò significa che sum_func_cptr è un puntatore costante a una funzione, cioè è possibile inizializzare con una funzione membro non-const, ma non è possibile modificare in seguito per puntare a un'altra funzione, perché const riferisce alla variabile. Ciò equivale a:

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

Non sei d'accordo? :-)

-Paolo

+0

non ci sono tipi di funzione qualificati cost. quindi 'const sum_func stuff = & Foo :: sum;' non ha senso, come dice la citazione dello standard nella mia risposta. Non sarebbe valido nemmeno dire 'sum_func * const sum_func_cptr = & Foo :: sum; '(* this * è un puntatore a funzione const), perché si prova ad assegnare un puntatore a un membro funzione a un puntatore a funzione. Dovresti fare 'sum_func Foo :: * const sum_func_cptr = & Foo :: sum;'. –

+0

Ho preso il post precedente come esempio. Definisce il nuovo tipo "sum_func" come funzione pointer-to-member: typedef int (Foo :: * sum_func) (int, int); Il mio punto era che "const" aggiunto a "sum_func" non lo cambia in "pointer-to-const-member-function". Francamente, non so nemmeno io per scrivere quel typedef. E non sapevo che potessi definire i tipi di funzione da soli, solo i puntatori alle funzioni. – Paolo