2012-12-29 12 views
7

Quando scrivo codice orientato agli oggetti in C, normalmente inserisco la struct definition insieme alle funzioni pubbliche in un file di intestazione e implemento le funzioni pubbliche in un file .c separato. Fornisco la parola chiave static a tutte le funzioni "private" per questa classe e le implemento anche nel file .c. Le funzioni pubbliche possono quindi chiamare le funzioni private appartenenti alla stessa classe. Le funzioni private non possono essere richiamate dall'esterno, grazie alla parola chiave static, quindi GCC può ottimizzare molte di queste funzioni. Sono spesso in linea e la funzione originale è completamente cancellata dal file oggetto di output.Collegamento interno per funzioni private C++?

Ora alla mia domanda: come posso fare lo stesso con le classi C++?

Diciamo che ho un file di intestazione:

class A { 
    int private_field; 
    int private_function(); 
public: 
    int public_function(); 
}; 

E il mio file cpp:

#include <iostream> 
#include "A.h" 

int A::private_function() { 
    std::cin >> private_field; 
    return private_field; 
} 

int A::public_function() { 
    return private_function() + 4; 
} 

Nel file oggetto risultante, private_function viene lasciato come un simbolo separato e public_function chiama private_function (non in linea). Vorrei dare il collegamento interno private_function, così il compilatore può fare le stesse ottimizzazioni di quando uso C. Ho provato con namespace anonimi e statici, ma non riesco a farlo funzionare come vorrei. Come farlo correttamente, è anche possibile? Io uso GCC.

+1

"Ho provato con domini anonimi e statici, ma non riesco a farlo funzionare come vorrei." che cosa è andato storto? –

+0

Ho risposto alla tua domanda, ma il compilatore dovrebbe essere in grado di eseguire la maggior parte delle ottimizzazioni, come ad esempio l'inline, che ha bisogno del collegamento interno per farlo. –

+0

Talvolta si esegue l'allineamento (per piccole funzioni), ma gli originali rimangono sempre => dimensione della libreria più grande. – Emil

risposta

8

I membri della classe non hanno mai un collegamento interno. Lo standard dice (sezione 9.3):

Le funzioni membro di una classe nello scope dello spazio dei nomi hanno un collegamento esterno. Le funzioni membro di una classe locale non hanno collegamenti.

Quindi, se si desidera creare funzioni di supporto con collegamento interno, è necessario utilizzare un non membro.

static int private_function(A* pThis); 

class A 
{ 
    int private_field; 
    friend int private_function(A* pThis); 
public: 
    int public_function(); 
}; 

e poi

#include <iostream> 
#include "A.h" 

static int private_function(A* pThis) 
{ 
    std::cin >> pThis->private_field; 
    return private_field; 
} 

int A::public_function() { 
    return private_function(this) + 4; 
} 

Si prega di notare questa regola dal standard (sezione 11.3):

Una funzione prima dichiarata in una dichiarazione amico ha linkage esterno. Altrimenti, la funzione mantiene il suo precedente collegamento.

+2

Penso che lo standard sia strano. Perché ti piacerebbe il collegamento esterno a funzioni private, quando non ci sono amici? – Emil

+6

@ Emil: Perché consente di integrare i membri pubblici in altre unità di traduzione. Considera se 'A :: public_function' è stato dichiarato in linea nella classe. È breve, quindi il compilatore vorrebbe inserirlo in tutti i siti di chiamata, in qualunque unità di traduzione essi compaiano.Ma poi 'private_function' deve essere collegabile a tutti quei siti. –

Problemi correlati