Рассмотрим следующий пример:
// 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 ]:
Используется Класс 1 (0x7fff0be4a6ff) до попадания
ИспользуетсяКласс 1 (0x7fff0be4a72e) doit hit
аналогично [EG1], но с включенной опцией -O2 [ EG2 ]:
Используется Класс 2 (0x7fffcef79fcf) до попадания
Бывший класс 1 (0x7fffcef79fff) доит
msvc2005 (14.00.50727.762) в Windows XP 32bit без оптимизации [ EG3 ]:
Используется Класс 1 (0012FF5B) до попадания
Б / уКласс 1 (0012FF67) доит
аналогично [EG3], но с включенным / O2 (или / Ox) [ EG4 ]:
Используется Класс 1 (0012FF73) до попадания
Б / уКласс 1 (0012FF7F) доит
Я ожидал бы либо ошибку компоновщика (при условии, что нарушено правило ODR), либо вывод, как в [EG2] (код встроен, из единицы преобразования ничего не экспортируется, правило ODR сохраняется). Итак мои вопросы:
- Почему возможны выходы [EG1], [EG3], [EG4]?
- Почему я получаю разные результаты от разных компиляторов или даже от одного и того же компилятора? Это заставляет меня думать, что стандарт как-то не определяет поведение в этом случае.
Спасибо за любые предложения, комментарии и стандартные интерпретации.
Update
Я хотел бы понять поведение компилятора. Точнее, почему нет ошибок, генерируемых в случае нарушения ODR. Гипотеза состоит в том, что, поскольку все функции в классах UsedClass1 и UsedClass2 помечены как встроенные (и, следовательно, C ++ 03 3.2 не нарушена), компоновщик не ' • сообщать об ошибках, но в этом случае выходные данные [EG1], [EG3], [EG4] кажутся странными.