Consideremos el siguiente ejemplo:C++: Diferentes clases con el mismo nombre en diferentes unidades de traducción
// 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();
}
El código se compila sin ningún error de compilador o enlazador. Pero la salida es extraño para mí:
gcc (Red Hat 4.6.1-9) en Fedora x86_64 sin optimización [EG1]:
UsedClass 1 (0x7fff0be4a6ff) doit golpe
UsedClass 1 (0x7fff0be4a72e) doit golpeómismo que [EG1] pero con O2 opción activado [EG2]:
UsedClass 2 (0x7fffcef79fcf) doit golpeó
UsedClass 1 (0x7fffcef79fff) doit golpeómsvc2005 (14.00.50727.762) en Windows XP de 32 bits sin optimización [EG3] :
UsedClass 1 (0012FF5B) doit golpeó
UsedClass 1 (0012FF67) doit golpeómismo que [EG3] pero con/O2 (o/Ox) activado [EG4]:
UsedClass 1 (0012FF73) doit golpeó
UsedClass 1 (0012FF7F) doit golpeó
yo esperaría que sea un error de vinculador (suponiendo que la regla es violada ODR) o la salida como en [EG2] (código se colocarán en línea, nada se exporta desde el translati en la unidad, se mantiene la regla de ODR). Por lo tanto, mis preguntas:
- ¿Por qué son posibles las salidas [EG1], [EG3], [EG4]?
- ¿Por qué obtengo resultados diferentes de compiladores diferentes o incluso del mismo compilador? Eso me hace pensar que el estándar de alguna manera no especifica el comportamiento en este caso.
Gracias por cualquier sugerencia, comentario e interpretación estándar.
Actualización
Me gustaría entender el comportamiento del compilador. Más precisamente, por qué no se generan errores si se infringe la ODR. Una hipótesis es que dado que todas las funciones en las clases UsedClass1 y UsedClass2 están marcadas como inline (y por lo tanto C++ 03 3.2 es no violado) el enlazador no informa errores, pero en este caso las salidas [EG1], [EG3], [EG4] parecen extrañas.
Se infringe el ODR, y no se garantiza un error del vinculador cuando eso sucede. El comportamiento no está definido. –
No puedo responder su pregunta en relación con los estándares, pero esta es la razón por la que tenemos espacios de nombres. – 111111