Come si evita di ridimensionare accidentalmente le costanti globali in C ++?
-
22-07-2019 - |
Domanda
Ho una classe di classe matrice modello definita in un'intestazione chiamata " Matrix.h " ;.
Alcune matrici vengono utilizzate ripetutamente nel mio programma. Ho pensato di definirli in "Matrix.h" file di intestazione, in questo modo:
const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
Quando lo faccio, g ++ si lamenta di aver ridefinito la costante in questione. Ciò accade perché includo Matrix.h in due diversi file di origine. Quando vengono compilati i file oggetto per questi, entrambi finiscono con una definizione della matrice sopra, causando il messaggio di errore.
La mia domanda è: come posso evitare questa situazione? Voglio una costante accessibile a più di un file, ma non so dove metterlo.
Soluzione
Se non si desidera dividerlo tra un'intestazione e un file di implementazione,
-
Dichiara il tuo costante
statico
(o dichiaralo nello spazio dei nomi anonimo) per rendere privata la definizione. Linker non si lamenterà, ma comporterà più copie private tra le unità di compilazione.static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
-
Crea una funzione inline che restituisce la costante. Le definizioni delle funzioni incorporate producono "debole" simboli nel file oggetto, quindi il linker eliminerà i duplicati e ne sceglierà uno.
inline const Matrix<GLfloat>& GET_B_SPLINE_TO_BEZIER_MATRIX() { const static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values); return B_SPLINE_TO_BEZIER_MATRIX; }
Altri suggerimenti
Lo eviti:
- Dichiarandolo
extern
nell'intestazione. Un simbolo può essere dichiarato un numero qualsiasi di volte. - Definendolo nell'implementazione, una sola volta.
scrivi semplicemente il tuo file header in questo modo
#ifndef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H
// il codice del file di intestazione
#endif
questo farà in modo che non venga dichiarato più volte
Avvolgere i file di intestazione (.h) nei condizionali del preprocessore per impedire che vengano inclusi due volte nella tabella dei simboli del compilatore:
#ifndef HEADER_NAME
#define HEADER_NAME
// code...
#endif//HEADER_NAME
HEADER_NAME può davvero essere qualsiasi cosa, ma è meglio assicurarsi che sia qualcosa correlato al file per evitare ulteriori collisioni, in quanto si tratta solo di definire una macro di preprocessore vuota (che finisce anche nella tabella dei simboli).