2015-04-04 2 views
12

Я читаю «C++ primer plus». В главе 9 он говорит о различии между C++ и C при работе с константным модификатором:Определение констант в нескольких файлах

«В C++ (но не в 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

UPDATE:

Если я

char* const constant = "Magic"; 

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

г ++ -Wall -g -o файл 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"; 
+0

Вы пытались использовать 'extern const char * constant;' в заголовке и, например, 'const char * constant =" Magic ";' в одном из единиц перевода? Глобалы по-прежнему различаются при использовании за пределами 'class' /' struct' declaratons. –

+0

@ πάνταῥεῖ Я думаю, что он означает, что 'const' должен иметь внутреннюю связь, поэтому компоновщик не должен жаловаться на дублирующие символы. – vsoftco

+0

@vsoftco _ «Я думаю, что он означает, что' const' должен иметь внутреннюю связь »_, что, очевидно, неверно, если только указанный в' struct' или 'class' также' static' не имеет значений в C++, которые отличаются от с. –

ответ

13

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

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

Update:

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

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

+0

Также стоит отметить, что 'const' квалифицирует все, что находится на его * левом *, за исключением случаев, когда он используется в качестве первого квалификатора, поэтому исходное определение такое же, как' char const * constant' - 'char' является' const' , но не указатель. –

+0

в const char * const константа, первый const сообщает, что символ, указанный указателем, является постоянным, а второй const указывает, что указатель указывает на постоянный адрес, правильно? Что это значит, если у меня есть char * const constant = «Magic»? Я обновил поведение, которое я получаю от своей программы. Я отвечу на ваш ответ, но если вы ответите на этот дополнительный вопрос, это действительно полезно! – drdot

+0

'char * const constant =" Magic "означает, что указатель является' const' (т. Е. Вы не можете переназначить указатель на другой строковый/строковый литерал C-стиля) и указывает на 'char'. Кроме того, C++ отказывается использовать указатель-к-char для указания на строковый литерал, он должен быть указателем на 'const char'. Другими словами, 'char * const constant =" Magic "' производит 'предупреждение: устаревшее преобразование из строковой константы в 'char *''. – vsoftco

Смежные вопросы