I am following this question for iterating over an enum.
enum class COLOR
{
Blue,
Red,
Green,
Purple,
First=Blue,
Last=Purple
};
COLOR operator++( COLOR& x ) { return x = (COLOR)(((int)(x) + 1)); }
COLOR operator*(COLOR c) {return c;}
COLOR begin(COLOR r) {return COLOR::First;}
// end iterator needs to return one past the end!
COLOR end(COLOR r) {return COLOR(int(COLOR::Last) + 1);}
The problem is that in my project, there are many cpp and hpp files which are compiled separately. It seems the compiler needs to have direct access to implementation of operator++. If I declare in a hpp and then implement in cpp file, I will face with error:
compiler warning: inline function ‘Color operator++(Color&)’ used but never defined
linker error: undefined reference to `operator++(instruction_type&)'
If I define it directly in hpp, I will face with another error
multiple definition of ...
for operator*, begin, and end in linker.
Adding the inline keyword in front of your 4 functions will allow them to be defined in the header without the multiple definition errors. For example:
inline COLOR operator*(COLOR c) {return c;}
Or you can include just the prototype in the .h file and define the functions in 1 .cpp file.
Related
I have been just tweaking around my game (putting class declaration in *.h files with their definition in the corresponding .cpp object files), but I don't quite understand when I have to use 'inline' keyword next to the method definitions and when I don't. Let me show you:
//shape.h
//header guards and includes in here
class shape
{
private:
char type;
int verticies[4][2];
int centre[2];
int radius;
public:
shape(int coordinates[4][2]);
shape(int coords[2], int r);
void Change(int coordinates[4][2]);
void Change(int coords[2], int r);
//more functions...
};
//shape.cpp
#include "shape.h"
inline shape::shape(int coordinates[4][2])//Constructor for a rectangle shape
{
for (int i=0; i<8; i++) //copy arguments to class
verticies[i/2][i%2]=coordinates[i/2][i%2];
//calculate centre of the rectangle
centre[0]=(coordinates[0][0]+coordinates[2][0])/2;
centre[1]=(coordinates[0][1]+coordinates[2][1])/2;
}
inline shape::shape(int coords[2], int r)//Constructor for a circle shape
{
type='C';
centre[0]=coords[0];
centre[1]=coords[1];
radius=r;
}
inline void shape::Change(int coordinates[4][2])//change coordinates of a rectangle shape
{
if (type=='C') return;//do nothing if a shape was a circle
for (int i=0; i<8; i++)
verticies[i/2][i%2]=coordinates[i/2][i%2];
centre[0]=(coordinates[0][0]+coordinates[2][0])/2;
centre[1]=(coordinates[0][1]+coordinates[2][1])/2;
if(verticies[0][0]-verticies[1][0]==0 || verticies[0][1]-verticies[1][1]==0) type='S'; else type='R';
}
inline void shape::Change(int coords[2], int r)//change coordinates for a circle shape
{
if (type=='R' || type=='S') return; //do nothing if a shape was not a circle
centre[0]=coords[0];
centre[1]=coords[1];
radius=r;
}
//and so on...
Not having an inline keyword would result in: "multiple definition of `shape::shape(int (*) [2])' " error. However on other occasions with other classes use of 'inline' was unneccesary. So my question is: when do I have to use 'inline' keyword and why is it important anyway?
Edit: So I have been informed that using inline in this situation is a bad Idea. Therefore what is a proper way to implement source and header files?
The inline keyword is important when you define a non-template function in a header file, but outside a class declaration. It avoids the multiple definition issue when a header is included in multiple places.
Other than that, it's not much use these days. It's technically still supposed to indicate that you want a function to use inline expansion -- i.e. instead of actually calling it (which presents a small overhead), the compiler just drops copies of the entire function body into whatever location it gets called from. (It's an invaluable optimisation for very small functions, such as accessor methods.) In reality though, compilers tend to figure out what should and shouldn't be inlined on their own, so it takes the keyword as little more than a hint.
In the version of the code you posted, inline key is completely unnecessary and actually harmful. In this version you have to remove all inline keywords from the code you posted to be able to properly compile and link it. What you posted will typically cause linker errors due to missing function definitions.
inline keyword becomes necessary if you move all your function definitions into the header file.
So, this is the simple rule you have to follow with inline keyword and member functions: If you define your member function in the header (.h) file, use inline keyword. If you define your member function in implementation (.cpp) file, don't use inline keyword.
I have the following 3 files (1 *.cpp and 2 *.hpp) :
the main program file:
// test.cpp
#include<iostream>
#include"first_func.hpp"
#include"sec_func.hpp"
int main()
{
double x;
x = 2.3;
std::cout << sec_func(x) << std::endl;
}
-
the first_func.hpp header:
// first_func.hpp
...
double first_func(double x, y, x)
{
return x + y + x;
}
-
the sec_func.hpp header:
// sec_func.hpp
...
double sec_func(double x)
{
double a, b, c;
a = 3.4;
b = 3.3;
c = 2.5;
return first_func(a,b,c) + x;
}
How do I properly call first_func from within the sec_func.hpp file?
For most functions, the implementation should reside in a compilation unit, that is a file that is going to be compiled by itself and compiled once.
Headers are not to be compiled by themselves*, instead they are included by multiple compilation units.
That's why your function definitions should reside in compilation units (like .cpp), not in headers. Headers should contain only the declarations (i.e. without the body), just enough so that other compilation units would know how to call them.
For completeness, the functions that generally need to be defined in headers (as an exception) are:
inline functions
template functions** (classes too)
Footnotes:
* headers can actually be pre-compiled, but that's a solution for speeding up compilation and it doesn't alter their purpose; don't get confused by that.
** you can put template function definitions outside of the headers if you use explicit template instantiation, but that's a rare case; the point is that every compilation unit that wants to instantiate a template (apply arguments to it) needs to have its complete definition, that's why template function definitions go into headers too.
It's a bad practice to place function definition to .hpp files. You should place only function prototypes there. Like this:
first_func.hpp:
double first_func(double x, double y, double x);
first_func.cpp:
double first_func(double x, double y, double x)
{
return x + y + x;
}
The same for second func.
And then, wherever you want to call your first_func, you just include corresponding first_func.hpp in that cpp module, and write the call.
Thus, every your module consists of hpp with all declarations, and cpp with definitions (that is, the bodies). When you need to reference something from this module, you include its hpp and use the name (of constant, variable, function, whatever).
And then you must link everything together:
gcc main.cpp first_func.cpp second_func.cpp -o program
To define a function in a header, you must mark it inline to prevent multiple definitions.
If you want to do this instead of separating the implementation to a separate file, you'll need to provide a prototype before calling the function (either by including the header (prefered) or declaring the function yourself).
// sec_func.hpp
#include "first_func.hpp"
//or
double first_func(double x, y, x); //declaration
double sec_func(double x)
{
double a, b, c;
a = 3.4;
b = 3.3;
c = 2.5;
return first_func(a,b,c) + x;
}
I'm having a headerfile called cnVector.h whose implementation is written in cnVector.cpp.
Those two files are located in the same directory.
cNormalCBP/
+ src/
+ cNormal/
+ cnUtils/
- cnVector.h
- cnVector.cpp
- main.cpp
The header contains a simple class definition.
class cnVector {
public:
cnVector(double, double, double);
inline cnVector cross(const cnVector&) const;
};
The implementation in the .cpp file is as follows:
#include "cnVector.h"
/* constructor */ cnVector::cnVector(double x, double y, double z)
: x(x), y(y), z(z) {
}
cnVector cnVector::cross (const cnVector& vOther) const {
return cnVector(
y * vOther.z + z * vOther.y,
z * vOther.x + x * vOther.z,
x * vOther.y + y * vOther.x );
}
Now, the following code from main.cpp breaks at line 3 because of an undefined reference to cnVector::cross(cnVector const&) const;
Note how the constructor-implementation is recognized, but not the cnVector::cross method.
int main() {
cnVector v1(1, 0, 0), v2(0, 1, 0);
cnVector v3 = v1.cross(v2);
}
I also get an error-message warning: inline function 'cnVector cnVector::cross(const cnVector&) const' used but never defined.
Copying the implementation into main.cpp works.
Can you explain to me why I can construct a cnVector instance but
the implementation of other methods are not recognized ?
Move your inline functions to your header file. Inline functions need their entire definitions in the header files because of how they integrate with the rest of your code. The compiler will (maybe) attempt to insert the code at all locations where the function is called, so it needs to be visible in the header file similar to how templates need to be entirely present in the header file.
I am making a math library (Actually copying one and modifying it.), But after all errors there is just one error I can't seem to get rid of. The Type specifier not found.
It is in line 201 of my Math.h which is this line:
int Classify(const Polygon &vcPoly);
I really tried searching google, but I didn't found anything. For me it's not quite that obvious whats wrong.
Here is the source of the Plane class. In the Math header are also vector, ray, matrix, and some more math classes. The class Polygon comes after the Plane class but I included the definition at the top of the header.
class Plane {
public:
Vector m_vcN, // plane normal vector
m_vcPoint; // point on plane
float m_fD; // distance to origin
//---------------------------------------
Plane(void) { /* nothing to do */ ; }
inline void Set(const Vector &vcN, const Vector &vcP);
inline void Set(const Vector &vcN, const Vector &vcP, float fD);
inline void Set(const Vector &v0, const Vector &v1, const Vector &v2);
inline float Distance(const Vector &vcPoint);
int Classify(const Polygon &vcPoly);
inline int Classify(const Vector &vcPoint);
bool Clip(const Ray*, float, Ray*, Ray*);
bool Intersects(const Vector &vc0, const Vector &vc1,
const Vector &vc2);
bool Intersects(const Plane &plane, Ray *pIntersection);
bool Intersects(const Aabb &aabb);
bool Intersects(const Obb &obb);
}; // class
Hope you could help me.
It seems like the type Polygon is not know in that line. Did you include the right header files? My guess is that Polygon.h (or something like that) is missing.
EDIT: if all classes are included in the same header, maybe you have to make sure that the class is defined (with a prototype) before it is needed as a type. That means you can place class prototypes in the beginning of your header file:
// prototype for Polygon
class Polygon;
This is a case of two header including each other:
Plane.h:
#include "Polygon.h"
Polygon.h
#include "Plane.h"
Since #include means 'preprocess the named file and insert contents here' this would lead to infinite recursion, which is why a common technique is to use 'include guards' in header file, in the form of:
#ifndef _SOMETHING_H_
#define _SOMETHING_H_
// header contents here
#endif
How this works, is if you include Polygon.h first, it defines the preprocessor symbol, and then goes on to include the files which you #include at the top of your header. One of these is Plane.h, which then in turn tries to include Polygon.h, but because Polygon's guard symbol is defined, it gets included as an empty file.
This prevents infinite recursion, but because of this there is no definition of Polygon type preceding the included Plane definition.
The solution is in at least one of these headers (and possibly in both) to replace the inclusion of header with a forward definition of the type. So in Plane.h instead of:
#include "Polygon.h"
you do:
class Polygon;
And you may do the same in Polygon.h.
Note that a forward declared type without a definition is what's called an incomplete type, and there are restrictions of how you can use it in the header: you may define pointers or references to it (which is how it's used in the example, but you may not define instances, pass by value, access fields etc.
I have a file called "SimpleFunctions.h" defined as follow:
#ifndef SIMPLEFUNCTIONS_H
#define SIMPLEFUNCTIONS_H
namespace my_namespace {
double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
float round(float r) { return round((double)r); }
}
#endif // SIMPLEFUNCTIONS_H
This file was previously included in only one file and it was working fine.
Now today I have included it in a second file and it no longer works. At link time, it tells me that the function is already defined in "firstfile.obj".
However, since I am using include guards, I would expect the functions to be defined only once, or am I missing something?
By default, these functions have external linkage. That means each translation unit has functions called double round(double r) and float round(float r), which causes a name collision at link time.
Some possible solutions are:
Declare the functions as static, which implies internal linkage
Inline the functions
Move the implementation out of the header and into a c/c++ file
Read more here:
What is external linkage and internal linkage?
By the way, include guards protect a single translation unit from including a header file multiple times. That's a different issue that what you're seeing here.
use 'inline'
inline double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
inline float round(float r) { return round((double)r); }
The compiler won't necessarily inline the code (although for this short func it may) but the linker doesn't treat is as a separate function anymore.
Note - include guards stop the same include file being included more than once in the same source file (strictly speaking 'compilation unit') it doesn't stop it being included in separate source files that are linked together. That's why you normally declare it in a header but define the function in a c file
A better way to solve the problem is through templates. Your code will compile fine if you were to do something along the lines of:
template <class T>
T round (T r) {
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
Your linker will stop complaining and you'll have a single function for all of your needs.
This solution can be improved with type traits. See boost::is_floating_point and boost::enable_if