несколько определений одного и того же класса - PullRequest
1 голос
/ 30 марта 2009

Играя с MSVC ++ 2005, я заметил, что, если один и тот же класс определяется несколько раз, программа все равно с удовольствием связывается, даже на самом высоком уровне предупреждения. Я нахожу это удивительным, почему это не ошибка?

module_a.cpp:

#include <iostream>
struct Foo {
  const char * Bar() { return "MODULE_A"; }
};
void TestA() { std::cout << "TestA: " << Foo().Bar() << std::endl; }

module_b.cpp:

#include <iostream>
struct Foo {
  const char * Bar() { return "MODULE_B"; }
};
void TestB() { std::cout << "TestB: " << Foo().Bar() << std::endl; }

main.cpp:

void TestA();
void TestB();
int main() {
  TestA();
  TestB();
}

И вывод:

TestA: MODULE_A
TestB: MODULE_A

Ответы [ 2 ]

3 голосов
/ 30 марта 2009

Это ошибка - код нарушает правило C ++ One Definition. Если вы сделаете это, стандарт говорит, что вы получаете неопределенное поведение.

Код ссылки, потому что если у вас было:

struct Foo {
  const char * Bar() { return "MODULE_B"; }
};

в обоих модулях не было бы нарушения ODR - в конце концов, это именно то, что делает #include заголовок. Нарушение происходит потому, что ваши определения отличаются (другое содержит строку "MODULE_A"), но компоновщик (который просто смотрит на имена классов / функций) не может это обнаружить.

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

Компилятор может посчитать, что объект бесполезен помимо его использования в функции Test # () и, следовательно, указывает на все это. Таким образом, компоновщик никогда не увидит, что какой-либо класс вообще существует! Просто идея, хотя.

Или, так или иначе, связь между TestA и классом Foo [#] будет выполняться внутри компиляции. Был бы конфликт, если компоновщик искал класс Foo (множественное определение), но компоновщик просто не ищет его!

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

...