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.
When you #include something you're basically copying and pasting that file into where you #included. 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.
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 of D shall consist of the same sequence of tokens
...
If the definitions of D do not satisfy these requirements, then the behavior is undefined.
Related
In my original code, I refer to the third-party .H in the ClassOne header file and everything works fine. Now, I received a new requirement that doesn't allow me to refer to the third-party .H in the ClassOne header file. So that the consumer of my code (i.e. ClassOne) will not have to indirectly includes the third-party .H file. I have tried the following modification but it doesn't work.
Here is the sample code:
// third_party.h
struct PPP
{
int x;
int y;
}; // without default constructor
// Original code!
//////////////////////////////////////////////
// ClassOne.h // my class
#include <third_party.h> // refer to the .H in header file
namespace X
{
class ClassOne
{
...
private:
boost::scoped_ptr<PPP> m_scpPPP;
};
}
// ClassOne.cpp
#include <third_party.h>
namespace X
{
ClassOne::ClassOne()
{
m_scpPPP.reset( new PPP() ); // fine
}
...
}
// Modified code!
==========================================================
// ClassOne.h
struct PPP; // error C2371: 'PPP' : redefinition; different basic types
namespace X
{
class ClassOne
{
...
private:
boost::scoped_ptr<PPP> m_scpPPP;
};
}
// ClassOne.cpp
#include <third_party.h>
namespace X
{
ClassOne::ClassOne()
{
m_scpPPP.reset( new PPP() ); // now see errors.
// error C2512: 'PPP' : no appropriate default constructor available
}
...
}
Question 1> Where should I forward declare the third-party struct type PPP?
Question 2> Why the compiler now complain about the PPP that has no default constructor?
It is not standard behavior to instantiate templates with incomplete types, therefore it shouldn't work boost::scoped_ptr.
Having said that, unique_ptr has a special rule, allowing to take incomplete types. If you use it (instead of boost::scoped_ptr), then it is done like this :
// forward declaration of PPP, assuming c++ header
struct PPP;
namespace X
{
class ClassOne
{
...
private:
std::unique_ptr<PPP> m_scpPPP;
};
}
Simply put: That won't work. Since you use PPP (and not PPP*) in side your ClassOne, the compiler needs to know the size at that point, so it needs to know the definition of PPP. To hide PPP from the public .h file, you'll have to do more. One possible solution is to hide your implementation class behind another class. Another would be only to refer to PPP* in your class declaration (although that would make the usage of scoped_ptr<> a bit pointless).
The compiler expects a default constructor because he assumes there is one. He needs the definition of the class to call "new" as well. You can work around this problem by moving the implementation of the ctor to the .cpp file, where you may include thirdParty.h.
I have a question concerning inlining methods.
I am using a library developed for collision models. One header file responsible for graphic interface contains declaration and implementation of the functions but the functions are not inlined. Therefore, it is impossible to include those functions in several translation units.
As an illustration here is a dummy code I designed for illustration :
LivingBeing.h
#ifndef LIVINGBEING_H
#define LIVINGBEING_H
class LivingBeing
{
public:
LivingBeing(double _size);
void breathe();
private:
double size;
};
//////////////
LivingBeing::LivingBeing(double _size)
{
size = _size;
}
void LivingBeing::breathe()
{
// do something
}
#endif
Forest.h
#ifndef FOREST_H
#define FOREST_H
#include "LivingBeing.h"
class Forest
{
public:
Forest(int _numberLivingBeings);
private:
int numberLivingBeings;
};
#endif
Forest.cpp
#include "Forest.h"
Forest::Forest(int _numberLivingBeings)
{
numberLivingBeings = _numberLivingBeings;
// Call LivingBeing constructor, methods etc...
}
Main.cpp
#include "Forest.h"
int main()
{
Forest forest = Forest(10);
return 0;
}
This code does not compile unless I add the inline keyword in front of the constructor LivingBeing and the method breathe. The error message is :
1>main_test.obj : error LNK2005: "public: __thiscall LivingBeing::LivingBeing(double)" (??0LivingBeing##QAE#N#Z) already defined in Forest.obj
1>main_test.obj : error LNK2005: "public: void __thiscall LivingBeing::breathe(void)" (?breathe#LivingBeing##QAEXXZ) already defined in Forest.obj
1>C:\Users\******\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\Test_3.exe : fatal error LNK1169: one or more multiply defined symbols found
My question is : what is the drawbacks of inlining methods ? The real library I am using is pretty large, I would like to inline methods from a specific file (in my example it would be LivingBeing.h) so that it is possible to use those methods in several .cpp files. What am I risking by changing the source file as such ?
Thanks a lot
You are defining functions (LivingBeing::LivingBeing and LivingBeing::breathe) in a header, which means there will be a definition in each translation unit that includes that header. This breaks the One Definition Rule (ODR), hence the link error.
You have three options:
Move the function definitions into a source file so they are only defined once; or
Declare them inline to allow multiple identical definitions; or
Move the definitions inside the class definition, which implicitly makes them inline.
what is the drawbacks of inlining methods ?
Possibly increased compilation time and executable size; but you'd need to measure to see whether there's any noticable difference.
A less stable API - client code will need recompiling whenever any inline function changes.
The possibility of accidentally breaking the ODR, for example if a function contains macros which might have different expansions in different translation units.
Just because a method is defined in a "source" file (.c/.cpp) doesn't mean it won't be inlined... link-time operations may perform that optimization. Oppositely, just because a method is declared and implemented as inline in a header file doesn't mean it will be inlined. In general, I define methods in a header file if they are very simple, e.g. int getWidth() const { return width; }, or MyObj* getNext() { return internal_itor ? internal_itor->next : 0; }
I am working in restructuring a former program which relies heavily on a external library
ChronoEngine.lib
I created a new project which holds the same additional include directories, linkers etc... than the former one
I have the following piece of code in a header file
#ifndef DRAW
#define DRAW
#include "physics/CHsystem.h"
class draw
{
public:
// Change size
static void changeSize(int w, int h);
// World definition
static void drawSky(double halfSize, double red, double green, double blue);
static void drawChair() ;
static void drawCDG() ;
static void drawPlane();
// Geometrical definition
static void drawSphere(ChBody* body);
static void drawBox(ChBody* body);
};
#endif
this is the same header file as in the previous project, but here visual studio does not find the definition of ChBody (which is included in the "physics/CHsystem.h" header file definition - this file includes physics/ChBody.h -)
when i right click on ChBody to find the reference, visual studio finds 5 references (1 is the real definition (from ChBody.h), 4 others are forward references in others files from the library)
how can I tell my program to find the real definition of the class ? Apparently, it is not a problem of being linked to the library, but more like a referencing problem
my main.cpp is only printing something to the screen for the time being, and draw.cpp is empty (i haven't defined the function i am declaring in draw.h for the time being)
Thanks
Best
Vincent
Thanks a lot
Actually that was a fairly easy problem to solve
The problem was coming from the fact that the other classes (such as ChBody) were defined in a namespace
therefore, adding
using namespace <the name of the namespace>;
before the definition of the class and after the #include solves this kind of issues.
Thanks
Best
Vincent
I'm trying to find a clean way to separate implementation details in C++ header files in a big project in order to achieve better information hiding and reduce build time. The problem with C++ is that every time you change a private member declaration, your dependent classes must be rebuilt.
This is a solution I came up with. Is it any good?
The basic Idea is to include a part of the cpp file conditionally in the header. this part contains the implementation declarations and is included only when the implementation file includes the header. in case of the external classes, this details are excluded from header. so client and implementation see two different version of header file. internal declaration changes won't affect clients(no compilation of dependent classes) and headers won't include private details.
Here is the implementation:
HEADER
#pragma once
class Dependency
{
public:
Dependency(void);
~Dependency(void);
void Proc(void);
//PRIVATE Implementaion details stays private
#ifdef Dependency_PRIVATE_IMPELEMENTATION
#define Dependency_PRIVATE_MODE 1
#include "Dependency.cpp"
#undef Dependency_PRIVATE_MODE
#endif
};
CPP
#define Dependency_PRIVATE_IMPELEMENTATION
#include "Dependency.h"
#undef Dependency_PRIVATE_IMPELEMENTATION
#ifdef Dependency_PRIVATE_MODE
private:
int _privateData;
#else
#include <iostream>
Dependency::Dependency(void)
{
//This line causes a runtime exception, see client
Dependency::_privateData = 0;
}
Dependency::~Dependency(void)
{
}
void Dependency::Proc(void)
{
std::cout << "Shiny happy functions.";
}
#endif
CLIENT
#include "stdafx.h"
#include "Dependency.h"
#pragma message("Test.Cpp Compiled")
int _tmain(int argc, _TCHAR* argv[])
{
Dependency d;
d.Proc();
return 0;
//and how I have a run time check error #2, stack around d ?!!
}
It's a pretty interesting question, really. Managing dependencies is important for big projects because the build times ramp up can make even the simplest change daunting... and when it happens people will try to hack it to avoid the rebuild-of-death (tm).
Unfortunately, it does not work.
The Standard explicitly says that classes definitions appearing in different translation units (roughly, files) should obey the One Definition Rule (see § 3.2 One definition rule [basic.def.odr]).
Why ?
The problem is a matter of impedance, in a way. The definition of a class contains information on the class ABI (Application Binary Interface), most notably, how such a class is layed out in memory. If you have different layouts of the same class in various translation units, then when putting it altogether, it won't work. It's as if one TU was speaking German and the other Korean. They might be attempting to say the same thing, they just won't understand each other.
So ?
There are several ways to manage dependencies. The main idea is that you should struggle, as much as possible, to provide "light" headers:
include as few things as possible. You can forward declare: types that are shown as arguments or return of functions declaration, types that are passed by reference or pointer but otherwise unused.
hide implementation details
Hum... What does it mean :x ?
Let's pick a simple example, shall we ?
#include "project/a.hpp" // defines class A
#include "project/b.hpp" // defines class B
#include "project/c.hpp" // defines class C
#include "project/d.hpp" // defines class D
#include "project/e.hpp" // defines class E
namespace project {
class MyClass {
public:
explicit MyClass(D const& d): _a(d.a()), _b(d.b()), _c(d.c()) {}
MyClass(A a, B& b, C* c): _a(a), _b(b), _c(c) {}
E e() const;
private:
A _a;
B& _b;
C* _c;
}; // class MyClass
} // namespace project
This header pulls in 5 other headers, but how many are actually necessary ?
a.hpp is necessary, because _a of type A is an attribute of the class
b.hpp is not necessary, we only have a reference to B
c.hpp is not necessary, we only have a pointer to C
d.hpp is necessary, we call methods on D
e.hpp is not necessary, it only appears as a return
OK, let's clean this up!
#include "project/a.hpp" // defines class A
#include "project/d.hpp" // defines class D
namespace project { class B; }
namespace project { class C; }
namespace project { class E; }
namespace project {
class MyClass {
public:
explicit MyClass(D const& d): _a(d.a()), _b(d.b()), _c(d.c()) {}
MyClass(A a, B& b, C* c): _a(a), _b(b), _c(c) {}
E e() const;
private:
A _a;
B& _b;
C* _c;
}; // class MyClass
} // namespace project
Can we do better ?
Well, first we can see that we call methods on D only in the constructor of the class, if we move the definition of D out of the header, and put it in a .cpp file, then we won't need to include d.hpp any longer!
// no need to illustrate right now ;)
But... what of A ?
It is possible to "cheat", by remarking that merely holding a pointer does not requires a full definition. This is known as the Pointer To Implementation idiom (pimpl for short). It trades off run time for lighter dependencies, and adds some complexity to the class. Here is a demo:
#include <memory> // don't really worry about std headers,
// they are pulled in at one time or another anyway
namespace project { class A; }
namespace project { class B; }
namespace project { class C; }
namespace project { class D; }
namespace project { class E; }
namespace project {
class MyClass {
public:
explicit MyClass(D const& d);
MyClass(A a, B& b, C* c);
~MyClass(); // required to be in the source file now
// because for deleting Impl,
// the std::unique_ptr needs its definition
E e() const;
private:
struct Impl;
std::unique_ptr<Impl> _impl;
}; // class MyClass
} // namespace project
And the corresponding source file, since that were the interesting things occur:
#include "project/myClass.hpp" // good practice to have the header included first
// as it asserts the header is free-standing
#include "project/a.hpp"
#include "project/b.hpp"
#include "project/c.hpp"
#include "project/d.hpp"
#include "project/e.hpp"
struct MyClass::Impl {
Impl(A a, B& b, C* c): _a(a), _b(b), _c(c) {}
A _a;
B& _b;
C* _c;
};
MyClass::MyClass(D const& d): _impl(new Impl(d.a(), d.b(), d.c())) {}
MyClass::MyClass(A a, B& b, C* c): _impl(new Impl(a, b, c)) {}
MyClass::~MyClass() {} // nothing to do here, it'll be automatic
E MyClass::e() { /* ... */ }
Okay, so that was the low and gritty. Further reading:
The Law of Demeter: avoid having to call multiple methods in sequences (a.b().c().d()), it means you have leaky abstraction, and forces you the include the whole world to do anything. Instead, you should be calling a.bcd() which hides the details from you.
Separate your code into modules, and provide a clear-well defined interface to each module, normally, you should have far more code within the module than on its surface (ie exposed headers).
There are many ways to encapsulate and hide information, your quest just begins!
This does not work. If you add anything to the class in the private .cpp file, the the users of the class will see a different class than what your implementation thinks it is.
This is not legal, and won't work in many cases. KDE has a great article on what you can and can't change in C++ to preserve ABI compatibility: Binary Compatibility Issues. If you break any of that with your "hidden" implementation, you're going to break the users.
Look at the pimpl idiom for a rather common way of doing what you are trying to achieve.
This won't work. You can easily see it because sizeof(Dependency) for the implementation and the client are different. The client basically sees a different class, accesses different locations in the memory and everything messes up!
Unfortunately, you cannot prevent a rebuild of dependent files if you change a class. However, you can hide the implementation details like this:
Header:
class privateData;
class Dependency
{
private:
privateData *pd;
public:
Dependency(void);
~Dependency(void);
void Proc(void);
};
cpp file
#include <Dependency.h>
class privateData
{
/* your data here */
};
Dependency::Dependency()
{
pd = new privateData;
}
Dependency::~Dependency()
{
if (pd)
delete pd;
}
void Dependency::Proc()
{
/* your code */
}
Note that this is not for you to copy paste. It's just to give you the idea. There may be missing error checking or code that is implied by this usage. One such thing is a copy constructor to prevent shallow copies.
Look at the Opaque_pointer pattern (aka pImpl)
The pattern is typically used for when the Class want to hide the internal implementation but is also have the benefit of that changes to the internal and private structures does not create a recompile since the binary call compatibility is maintained.
The problem with doing it any other way, is that binary compatibility is probably NOT maintained when you changed anything in the class definition, and hence all software will have to be recompiled.
It looks like your solution is a attempt to do exactly this, however you should user a (void*) instead of a int so as to make sure the software compiles correctly on 32 and 64 bit compilers on different platforms -- and just use the cook-book example of Opaque Pointers.
See the code, then you would understand what I'm confused.
Test.h
class Test {
public:
#ifndef HIDE_VARIABLE
int m_Test[10];
#endif
};
Aho.h
class Test;
int GetSizeA();
Test* GetNewTestA();
Aho.cpp
//#define HIDE_VARIABLE
#include "Test.h"
#include "Aho.h"
int GetSizeA() { return sizeof(Test); }
Test* GetNewTestA() { return new Test(); }
Bho.h
class Test;
int GetSizeB();
Test* GetNewTestB();
Bho.cpp
#define HIDE_VARIABLE // important!
#include "Test.h"
#include "Bho.h"
int GetSizeB() { return sizeof(Test); }
Test* GetNewTestB() { return new Test(); }
TestPrj.cpp
#include "Aho.h"
#include "Bho.h"
#include "Test.h"
int _tmain(int argc, _TCHAR* argv[]) {
int a = GetSizeA();
int b = GetSizeB();
Test* pA = GetNewTestA();
Test* pB = GetNewTestB();
pA->m_Test[0] = 1;
pB->m_Test[0] = 1;
// output : 40 1
std::cout << a << '\t' << b << std::endl;
char temp;
std::cin >> temp;
return 0;
}
Aho.cpp does not #define HIDE_VARIABLE, so GetSizeA() returns 40, but
Bho.cpp does #define HIDE_VARIABLE, so GetSizeB() returns 1.
But, Test* pA and Test* pB both have member variable m_Test[].
If the size of class Test from Bho.cpp is 1, then pB is weird, isn't it?
I don't understand what's going on, please let me know.
Thanks, in advance.
Environment:
Microsoft Visual Studio 2005 SP1 (or SP2?)
You violated the requirements of One Definition Rule (ODR). The behavior of your program is undefined. That's the only thing that's going on here.
According to ODR, classes with external linkage have to be defined identically in all translation units.
Your code exhibits undefined behavior. You are violating the one definition rule (class Test is defined differently in two places). Therefore the compiler is allowed to do whatever it wants, including "weird" behavior.
In addition to ODR.
Most of the grief is caused by including the headers only in the cpp files, allowing you to change the definition between the compilation units.
But, Test* pA and Test* pB both have member variable m_Test[].
No, pB doesn't have m_Test[] however the TestPrj compilation unit doesn't know that and is applying the wrong structure of the class so it will compile.
Unless you compile in debug with capturing of memory overrun you would most times not see a problem.
pB->m_Test[9] = 1; would cause writing to memory not assigned by pB but may or may not be a valid space for you to write.
Like many people told here, you've violated the so-called One Definition Rule (ODR).
It's important to realize how C/C++ programs are assembled. That is, the translation units (cpp files) are compiled separately, without any connection to each other. Next linker assembles the executable according to the symbols and the code pieces generated by the compiler. It doesn't have any high-level type information, hence it's unable (and should not) to detect the problem.
So that you've actually cheated the compiler, beaten yourself, shoot your foot, whatever you like.
One point that I'd like to mention is that actually ODR rule is violated very frequently due to subtle changes in the various include header files and miscellaneous defines, but usually there's no problem and people don't even realize this.
For instance a structure may have a member of LPCTSTR type, which is a pointer to either char or wchar_t, depending on the defines, includes and etc. But this type of violation is "almost ok". As long as you don't actually use this member in differently compiled translation units there's no problem.
There're also many other common examples. Some arise from the in-class implemented member functions (inlined), which actually compile into different code within different translation units (due to different compiler options for different translation units for instance).
However this is usually ok. In your case however the memory layout of the structure has changed. And here we have a real problem.