Как избежать случайного повторного выделения глобальных констант в C ++? - PullRequest
4 голосов
/ 13 марта 2009

У меня есть класс класса матрицы шаблона, определенный в заголовке с именем "Matrix.h".

В моей программе неоднократно используются определенные матрицы. Я думал, что я определю их в заголовочном файле Matrix.h, например:

const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);

Когда я делаю это, g ++ жалуется, что я переопределил эту константу. Это происходит потому, что я включаю Matrix.h в два разных исходных файла. Когда объектные файлы для них скомпилированы, оба заканчивают определением матрицы выше, вызывая сообщение об ошибке.

Мой вопрос: как мне избежать этой ситуации? Я хочу, чтобы константа была доступна более чем одному файлу, но я не знаю, куда ее поместить.

Ответы [ 4 ]

8 голосов
/ 13 марта 2009

Вы избегаете этого:

  • Объявление его extern в шапке. Символ может быть объявлен любое количество раз.
  • Определение его в реализации, только один раз.
6 голосов
/ 13 марта 2009

Если вы не хотите разделять его между заголовком и файлом реализации,

  1. Объявите вашу константу static (или объявите ее в анонимном пространстве имен), чтобы сделать определение частным. Линкер не будет жаловаться, но это приведет к нескольким частным копиям в разных единицах компиляции.

    static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
    
  2. Создайте встроенную функцию, которая возвращает константу. Определения встроенных функций производят «слабые» символы в объектном файле, поэтому компоновщик удалит дубликаты и выберет один.

    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;
    }
    
0 голосов
/ 13 марта 2009

Обернуть файлы заголовков (.h) в условные выражения препроцессора, чтобы предотвратить их двойное включение в таблицу символов компилятора:

#ifndef HEADER_NAME
#define HEADER_NAME
// code...
#endif//HEADER_NAME

HEADER_NAME действительно может быть чем угодно, но лучше убедиться, что это что-то связанное с файлом, чтобы предотвратить новые коллизии, так как это всего лишь определение пустого макроса препроцессора (который также заканчивается в таблице символов).

0 голосов
/ 13 марта 2009

просто напишите свой заголовочный файл следующим образом

# ifndef HEADER_FILE_NAME_H

# определить HEADER_FILE_NAME_H

// код вашего файла заголовка

# ENDIF

это гарантирует, что он не будет объявлен несколько раз

...