C++: Разные классы с одинаковым именем в разных единицах трансляции

Рассмотрим следующий пример:

// usedclass1.hpp  
#include <iostream>  
class UsedClass
{  
public:
  UsedClass() { }  
  void doit() { std::cout << "UsedClass 1 (" << this << ") doit hit" << std::endl; }
};  

// usedclass2.hpp  
#include <iostream>
class UsedClass
{
public:
  UsedClass() { }
  void doit() { std::cout << "UsedClass 2 (" << this << ") doit hit" << std::endl; }
};

// object.hpp
class Object
{
public:
  Object();
};

// object.cpp
#include "object.hpp"
#include "usedclass2.hpp"
Object::Object()
{
  UsedClass b;
  b.doit();
}

// main.cpp
#include "usedclass1.hpp"
#include "object.hpp"
int main()
{
  Object obj;
  UsedClass a;
  a.doit();
}

Код компилируется без каких-либо ошибок компилятора или компоновщика. Но вывод для меня странный:

  • gcc (Red Hat 4.6.1-9) на Fedora x86_64 без оптимизации [EG1]:

    UsedClass 1 (0x7fff0be4a6ff) doit hit
    . UsedClass 1 (0x7fff0be4a72e) doit hit

  • то же, что и [EG1], но с включенной опцией -O2 [EG2]:

    UsedClass 2 (0x7fffcef79fcf) doit hit
    UsedClass 1 (0x7fffcef79fff) doit hit

  • msvc2005 (14.00.50727.762) на Windows XP 32bit без оптимизации [EG3]:

    UsedClass 1 (0012FF5B) doit hit
    UsedClass 1 (0012FF67) doit hit

  • то же, что и [EG3], но с включенным /O2 (или /Ox) [EG4]:

    UsedClass 1 (0012FF73) doit hit
    UsedClass 1 (0012FF7F) doit hit

Я бы ожидал либо ошибку компоновщика (предполагая, что нарушено правило ODR), либо вывод, как в [EG2] (код инлайнится, ничего не экспортируется из блока трансляции, правило ODR соблюдается). Итак, мои вопросы:

  1. Почему возможны выходы [EG1], [EG3], [EG4]?
  2. Почему я получаю разные результаты от разных компиляторов или даже от одного и того же компилятора? Это заставляет меня думать, что стандарт как-то не определяет поведение в этом случае.

Спасибо за любые предложения, комментарии и толкования стандарта.

Обновление
Хотелось бы понять поведение компилятора. Точнее, почему не выдаются ошибки при нарушении УСО. Есть гипотеза, что поскольку все функции в классах UsedClass1 и UsedClass2 помечены как inline (и поэтому C++03 3.2 не нарушен), то компоновщик не сообщает об ошибках, но в этом случае выходы [EG1], [EG3], [EG4] выглядят странно.

7
задан user1221434 20 February 2012 в 16:58
поделиться