1

Tengo un objeto global definido en un archivo "objeto.h" de la forma:

#ifndef objetoo__h
#define objetoo__h
typedef struct objeto {
  int a;
} objeto;
objeto objetin;
#endif

Luego defino una clase en "clase.h" y su implementación en "clase.cpp". En clase.h procedo de la siguiente forma:

#ifndef clase__h
#define clase__h
#include "objeto.h"
extern objeto objetin;
class clase { ...
}
#endif

En clase.cpp simplemente pongo en la directivas del preprocesador:

#include "clase.h"

Es en clase.cpp donde hago uso del objeto global objetin. El problema que tengo es que despues, haciendo uso de un tercer archivo main.cpp en el que incluyo "objeto.h" y "clase.h" y de nuevo declaro extern objetin, el compilador g++ me da error por definiciones multiples de objetin, sin embargo, si en lugar de usar un archivo separado para la implementación de clase.h, pongo las definiciones de los metodos en clase.h, este problema desaparece. ¿Por qué ocurre esto?

sstan
  • 16,591
  • 2
  • 21
  • 45
badabum
  • 34
  • 5
  • Por favor provee el ejemplo completo, ya que quizas implementemos lo faltante de forma incorrecta. Tu debes proveer un [mcve] –  Dec 03 '17 at 17:02

1 Answers1

2

¿Por qué ocurre esto?

Porque no estás entendiendo cómo funcionan las Unidades de Traducción y las inclusiones, aquí tienes dos hilos que explican cada uno de esos conceptos:

Tras leer esos dos hilos, te será más fácil entender este esquema:

La condición para que un objeto marcado como extern funcione es que puede tener múltiples declaraciones pero sólo una definición. Los archivos de cabecera (.h o .hpp) no generan Unidad de Traducción (UdT), son copia-pegados directamente sobre un archivo de código (.cpp).

Por lo tanto tu definición objeto objetin; va a parar tanto a la UdT de clase.cpp como a la UdT de main.cpp, en esta última no recibes dos definiciones de objetin por las guardas de inclusión que añadiste en objeto.h, de no haberlas puesto recibirías un objeto objetin; desde objeto.h y desde clase.h.

En el momento de invocar al enlazador, nos encontramos que objetin está declarado como extern en clase.h y definido tanto en clase.cpp como en main.cpp y el enlazador se queja de definición múltiple.

Solución.

Es en clase.cpp donde hago uso del objeto global objetin.

Si esto es cierto, mueve la definición objeto objetin; de objeto.h a clase.cpp.

En C++ struct no forma parte del tipo.

En C++ no es necesario anteponer struct antes de los tipos estructura, tu definición de objeto puede quedar así:

struct objeto {
  int a;
};
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82