C++/VS2005: определение одного и того же имени класса в двух разных файлах.cpp

Что-то вроде академического вопроса, но я столкнулся с этим, когда писал некоторые юнит-тесты.

Мой фреймворк для модульных тестов (UnitTest++) позволяет создавать структуры, служащие в качестве фиксаторов. Обычно они настраиваются для тестов в файле, поэтому я помещаю их в начало файла модульных тестов.

//Tests1.cpp

struct MyFixture {  MyFixture() { ... do some setup things ...} };

TEST_FIXTURE(MyFixture, SomeTest)
{
  ...
} 

//Tests2.cpp

struct MyFixture { MyFixture() { ... do some other setup things, different from Tests1}};

 TEST_FIXTURE(MyFixture, SomeOtherTest)
 {
  ...
 }

Однако недавно я обнаружил (по крайней мере, с VS2005), что когда вы называете структуру фикстура, используя одно и то же имя (так что теперь две версии структуры существуют с одинаковым именем), одна из версий автоматически отбрасывается. Это довольно удивительно, потому что мой компилятор установлен на /W4 (самый высокий уровень предупреждения), и предупреждение не выдается. Я предполагаю, что это конфликт имен, и почему были изобретены пространства имен, но нужно ли мне оборачивать каждое из моих модульных тестовых устройств в отдельное пространство имен? Я просто хочу убедиться, что я не пропускаю что-то более фундаментальное.

Есть ли лучший способ исправить это - должно ли это происходить? Разве я не вижу ошибку повторяющихся символов или что-то?

3 ответа

Решение

Попробуйте поместить классы в анонимное пространство имен, вам может показаться, что это менее неприятно, чем необходимость создавать и именовать новое пространство имен для каждого файла.

У меня нет доступа к VS2005 и Cpp, но это может сработать..

//Tests1.cpp
namespace
{
struct MyFixture {  MyFixture() { ... do some setup things ...} };
}

TEST_FIXTURE(MyFixture, SomeTest)
{
  ...
} 


//Tests2.cpp
namespace
{
struct MyFixture { MyFixture() { ... do some other setup things, different from Tests1}};
}

TEST_FIXTURE(MyFixture, SomeOtherTest)
{
 ...
}

Компилятор работает только на одном модуле компиляции одновременно; это будет исходный файл и все, что оно включает. Так как ваши классы находятся в разных файлах, никаких конфликтов нет.

Компоновщик собирает все вместе, но он не знает об определениях классов, поэтому он также не видит конфликта.

Когда-то во времена Си, для компоновщика было достаточно распознать, что у вас две разные функции с одним и тем же именем, и сгенерировать сообщение об ошибке. Со встроенными функциями и шаблонами в C++ он больше не может этого делать - разные модули компиляции часто содержат дубликаты одной и той же функции, поэтому компоновщик просто предполагает, что они одинаковы.

В основном это является следствием того факта, что классы должны быть определены в заголовочных файлах, что приводит к избыточным определениям классов в каждом объектном файле. Таким образом, компоновщик, который может обрабатывать связи C++, должен сложить избыточные объявления классов и сделать вид, что класс был объявлен только один раз.

Компоновщик никак не может различить один класс, включенный в несколько объектов, и несколько классов с одинаковым именем в нескольких объектах.

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

Другие вопросы по тегам