Подтвердить что ты не робот

Постоянное определение в нескольких файлах

Я читаю "С++ primer plus". В главе 9 он говорит о различии между С++ и C при работе с модификатором const:

"В С++ (но не в C) модификатор const незначительно меняет классы хранения по умолчанию. Если глобальная переменная имеет внешнюю привязку по умолчанию, глобальная переменная const по умолчанию имеет внутреннюю привязку.

...

Если глобальная константная декларация имела внешнюю связь как регулярную переменную, это будет ошибкой, потому что вы можете определить глобальную переменную только в одном файле. То есть, только один файл может содержать объявление процедуры, а другие файлы должны предоставлять ссылочные объявления с использованием ключевых слов extern. "

Я попытался проверить это требование со следующей программой:

file.h:

using namespace std;

const char *constant = "Magic";

file1.cpp

#include <iostream>
#include "file.h"
extern void file2();
int main(){
  cout << "constant = " << constant << endl;
  file2();
}

file2.cpp

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

void file2(){
  cout << "file2 constant = " << constant << endl;
}

Makefile:

CFLAGS = -Wall -g
INCLUDE = file.h
src = file2.cpp file1.cpp

all: $(src) $(INCLUDE)
  g++ $(CFLAGS) -o file $(src)

clean:
  rm -f file

Когда я это сделаю, я получаю следующее сообщение об ошибке:

g++ -Wall -g -o file file2.cpp file1.cpp
/tmp/ccdl16Tw.o:(.data+0x0): multiple definition of `constant'
/tmp/ccA3ZEHa.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [all] Error 1

gcc версия 4.8.2

ОБНОВЛЕНИЕ:

Если я делаю

 char* const constant = "Magic";

Тогда make даст мне это предупреждение:

g++ -Wall -g -o file file2.cpp file1.cpp

In file included from file2.cpp:2:0:
file.h:3:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
 char* const constant = "Magic";
                        ^
In file included from file1.cpp:2:0:
file.h:3:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
 char* const constant = "Magic";
4b9b3361

Ответ 1

const char *constant не const. Это указатель не const на const char. Будучи переменной non const в пространстве имен, она по умолчанию имеет внешнюю привязку и, следовательно, вы получаете множественную ошибку определения.

const char * const constant const и будет вести себя так, как вы ожидаете.

Update:

char* const constant, с другой стороны, будет указателем const на char. Будучи const, он имеет внутреннюю связь по умолчанию в области пространства имен.

Однако вы не должны инициализировать его строковым литералом (как указывает предупреждение компилятора), потому что это недопустимо стандартом (такое преобразование является незаконным в С++ 11 и ранее было устаревшим). Строковые литералы могут храниться в памяти только для чтения, и вам не разрешается изменять их во время выполнения. Вот почему опасно указывать на строковый литерал с указателем на не const char.