Reputation: 22922
I lost most of this afternoon tracking down a bug which basically came down to including two different versions of the same header file declaring the same class in Visual Studio 2015. Greatly simplified, it appears as follows;
oldcamera.h
#pragma once
class camera
{
public:
camera();
int a;
double x,y,z;
};
camera.h
#pragma once
class camera
{
public:
camera();
double x,y,z;
};
camera.cpp
#include camera.h
camera::camera()
{
x = y = 0;
z = 1;
};
mytransclass.h
#pragma once
#include "oldcamera.h"
class trans
{
public:
camera m_camera;
};
func.cpp
#include "mytransclass.h"
void MyFunc(trans *ptrans)
{
ptrans->x = 1.0;
ptrans->y = 2.0;
ptrans->z = 3.0;
}
The project includes camera.cpp and func.cpp, and when single stepping through MyFunc, the debugger showed the assignments weren't actually doing anything. Question is whether this should compile and link without warning, and if it is legal (which knowing the convoluted heritage of c++ is likely), why does the assignment fail? If it is legal, is there any way to flag it as an error? Compiler is Visual C++ 2015.
Upvotes: 1
Views: 196
Reputation: 41301
Your program violates One Definition Rule, which in particular says ([basic.def.odr]/6):
There can be more than one definition of a class type (Clause 9), ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named
D
defined in more than one translation unit, then
(6.1) — each definition ofD
shall consist of the same sequence of tokens
...
If the definitions ofD
do not satisfy these requirements, then the behavior is undefined.
Upvotes: 1
Reputation: 28178
When you #include
something you're basically copying and pasting that file into where you #include
d. It's not actually an error to have multiple of the same class definition, as long they are not multiple of the same class definition being included into the same compilation unit (cpp). If you do that, it breaks the one definition rule.
In your setup, the functions in the version of Camera in oldcamera.h are calling the functions written for camera.h (since those functions are the only which were compiled, since you said oldcamera.cpp wasn't in the project). However, those functions rely on the data layout of the class Camera being a certain way. Since oldcamera.h
's Camera
and new camera.h
's Camera
have a different data layout (which you didn't demonstrate, but I'm assuming), shit hits the fan.
Upvotes: 1