Является ли это ошибкой VC++ 2010? Об объявлении константного объекта в заголовке

Несколько строк кода стоят тысячи слов:

У меня есть три простых файла: header.h, main.cpp, other.cpp

==== CODE BEGIN ====

// header.h  
  #pragma once  

const void* p = 0;

// main.cpp

  #include "header.h"

int main()
{
    return 0;
}

// other.cpp

  #include "header.h"
==== CODE END ====

При компиляции простейшего проекта VC++ 2010 жалуется на следующее:

ClCompile:
  other.cpp
  main.cpp
  Generating Code...
other.obj : error LNK2005: "void const * const p" (?p@@3PBXB) already defined in main.obj
D:\Test\Debug\bug.exe : fatal error LNK1169: one or more multiply defined symbols found

Build FAILED.

Time Elapsed 00:00:00.29
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Я уверен, что это ошибка VC++ 2010 из-за следующих двух ссылок:

  1. #P5# <блочная цитата> #P6#
  2. #P7# <блочная цитата> #P8# #P9#

person xmllmx    schedule 15.11.2010    source источник
comment
Немного форматировал. Используйте кнопки над полем редактирования для правильного форматирования кода и кавычек.   -  person Björn Pollex    schedule 15.11.2010


Ответы (3)


const void *p = 0; определяет p как указатель на const void, но не определяет сам p как const вообще. Поскольку ваш p не является объектом const, правило, придающее ему внутреннюю связь, не применяется, поэтому у него есть внешняя связь.

void *const p = 0; определяет p как постоянный указатель. void const * const p будет определять p как константный указатель на const void.

person Jerry Coffin    schedule 15.11.2010

Если вы определяете переменную в заголовочном файле, который включается более одного раза, компоновщик находит определение для каждого включения. Вы должны объявить переменную в заголовочном файле и определить ее один и только один раз в одном файле .cpp.

Заголовочный файл:

extern const void* p;

СРР-файл:

const void* p = 0;
person Steve Townsend    schedule 15.11.2010
comment
Большое спасибо за быстрый ответ. - person xmllmx; 15.11.2010
comment
#pragma Once inline const int& GetConst() { return 8; } const int& r = GetConst(); - person xmllmx; 15.11.2010
comment
Если я перепишу header.h следующим образом, то ошибка компилятора повторится:#pragma Once inline const int& GetConst() { return 8; } const int& r = GetConst(); - person xmllmx; 15.11.2010
comment
Однако переменная с областью действия пространства имен, объявленная const, имеет внутреннюю связь. - person James McNellis; 15.11.2010
comment
@James - было бы хорошо, если бы OP перестал определять переменные в своем заголовочном файле. Для него это блокировщик сборки независимо от нюансов типа переменной. Извините, что мутил воду. - person Steve Townsend; 15.11.2010

Может быть, это должно быть void* const p?

person Dialecticus    schedule 15.11.2010