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;
}
Related
I'm working on a fairly large project (3D graphics engine) and I've run into some trouble while restructuring the code a bit. I want to have all of my classes implemented in single files (only have .hpp rather than having both a .cpp and .hpp file for each class). I don't have a specific reason for doing it this way other than just wanting to, but I'm hoping to avoid discussions over what C++ best practices are.
When I do it this way I get a series of multiple definition errors that look like this:
/tmp/ccztDQam.o: In function `Point3DH::normalize()':
Renderer.cpp:(.text+0x736): multiple definition of `Point3DH::normalize()'
/tmp/ccawpiuU.o:main.cpp:(.text+0x1a6de): first defined here
/tmp/ccztDQam.o: In function `Point3DH::dot(Point3DH, Point3DH)':
Renderer.cpp:(.text+0x79e): multiple definition of `Point3DH::dot(Point3DH, Point3DH)'
/tmp/ccawpiuU.o:main.cpp:(.text+0x1a746): first defined here
/tmp/ccztDQam.o: In function `Point3DH::cross(Point3DH, Point3DH)':
Renderer.cpp:(.text+0x7d6): multiple definition of `Point3DH::cross(Point3DH, Point3DH)'
/tmp/ccawpiuU.o:main.cpp:(.text+0x1a77e): first defined here
...
The issue comes when the classes start including each other and code is repeated multiple times. It seems that header guards are not sufficient as explained in this answer. I'm wondering if there is any way to get around this or an alternate way to achieve the goal.
The project is organized into modules (folders) such as geometry or polygon which contain relevant classes so include paths go to the parent directory and then into the correct module and class
For reference, here is what one of the files looks like (./graphics/Raster.hpp):
#ifndef GRAPHICS_RASTER
#define GRAPHICS_RASTER
#include "../graphics/Colour.hpp"
#include <vector>
class Raster {
private:
std::vector<Colour> image;
std::vector<double> zBuffer;
int width;
int height;
public:
Raster(int, int, Colour);
void setPixel(int, int, double, Colour);
int getWidth();
int getHeight();
};
#endif
#ifndef GRAPHICS_RASTER_IMPLEMENTATION
#define GRAPHICS_RASTER_IMPLEMENTATION
#include "../graphics/Colour.hpp"
#include <vector>
#include <limits>
Raster::Raster(int width, int height, Colour clear) :
image(std::vector<Colour>(width*height, clear)),
zBuffer(std::vector<double>(width*height, -std::numeric_limits<double>::max())),
width(width),
height(height)
{}
void Raster::setPixel(int x, int y, double z, Colour c) {
if(x < 0 || x >= width || y < 0 || y >= height) return;
if(z <= zBuffer[(height - y - 1)*width + x]) return;
image[(height - y - 1)*width + x] = c;
zBuffer[(height - y - 1)*width + x] = z;
}
int Raster::getWidth() {return width;}
int Raster::getHeight() {return height;}
#endif
If you for some reason want to implement everything in header files, you have to make all your functions inline. Functions defined in class definitions are implicitly inline. Functions defined out-of-class have to be declared with inline keyword explicitly.
That's what you have to do with every definition that you have in the "implementation" section of your header - add explicit inline keyword to every function definition. E.g.
inline void Raster::setPixel(int x, int y, double z, Colour c) {
if(x < 0 || x >= width || y < 0 || y >= height) return;
if(z <= zBuffer[(height - y - 1)*width + x]) return;
image[(height - y - 1)*width + x] = c;
zBuffer[(height - y - 1)*width + x] = z;
}
and so on.
Of course, you can also move all your member function definitions into class definition (which will make them inline), but that will preclude such distinctly separated two-section header structure as you have now. I don't know how important it is to you.
Every time your header is included in a cpp file, you create a new copy of the implementation.
You need to make sure that the implementation is only used in one cpp file - or inline every method.
This guide have good ideas on doing that:
https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
examples:
https://github.com/nothings/stb
Basically:
1-make a #define UNIQUE_NAME_IMP and #define UNIQUE_NAME_HEADER to make implementation and declaration visible on different files by using:
your implementation:
#ifdef _DECL_
type declaration
function prototype
#endif
#ifdef _IMPL_
code
#endif
and in another file that will use it:
#define _DECL_
#include <my_header.h>
code...
...
//use this only once to avoid
//duplicate symbol like you mentioned in your post.
#define _IMPL_
#include <my_header.h>
2-avoid memory allocation, make your functions use the memory you pass on with your structures.
3-avoid external dependencies. Each dependency will make you use flags or create requirements to comply before using your header...
4-use "static". This makes the implementation private to the source file that creates it.
I'm new to classes and object-oriented programming. Our instructor is having us create a program that must have a .cpp file, a main .cpp file, and a .hpp file.
Here are each of the files:
First, the odometer.hpp file:
class Odometer
{
int miles;
float gallons, mpg;
public:
//Constructors
Odometer(); //Default
Odometer(float g, int m);
//Mutator Functions
void Set_miles(int m);
void Set_gallons(float g);
//Functions
void Add_trip(int m, float g);
int Check_mileage(float g);
void Print_info();
//Accessor Functions
float Get_mpg();
float Get_gallons();
int Get_miles();
};
Next, the odometer.cpp file:
#include "odometer.hpp"
#include <iostream>
//Constructors
Odometer::Odometer()
{
miles = 0;
gallons = 0.0;
mpg = 0.0;
}
Odometer::Odometer(float g, int m)
{
miles = m;
gallons = g;
mpg = m / g;
}
//Mutator functions
void Odometer::Set_miles(int m)
{
miles = m;
}
void Odometer::Set_gallons(float g)
{
gallons = float(g);
}
//Accessor functions
float Odometer::Get_mpg()
{
return mpg;
}
float Odometer::Get_gallons()
{
return gallons;
}
int Odometer::Get_miles()
{
return miles;
}
//Other functions
//Takes # of gallons & # of miles and adds it to previous values, calculating
//new miles/gallon for whole trip
void Odometer::Add_trip(int m, float g)
{
miles += m;
gallons += g;
mpg = miles / gallons;
}
int Odometer::Check_mileage(float g)
{
int newMiles = g * mpg;
return newMiles;
}
void Odometer::Print_info()
{
std::cout << "Miles: " << miles << " Gallons: " << gallons <<
" Miles/Gallon: " << mpg;
}
And finally, the odometer_main.cpp file (so far, it's incomplete):
#include <iostream>
#include "odometer.cpp"
using namespace std;
int main(void)
{
//Odometer odDefault; //Odometer object set to defaults
Odometer od(10, 100); //Odometer object with values set
return 0;
}
These are the errors I'm getting when I try compiling all the files:
/tmp/ccArjYHP.o: In function 'Odometer::Odometer()':
odometer_main.cpp:(.text+0x0): multiple definition of 'Odometer::Odometer()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Odometer()':
odometer_main.cpp:(.text+0x0): multiple definition of 'Odometer::Odometer()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Odometer(float, int)':
odometer_main.cpp:(.text+0x30): multiple definition of 'Odometer::Odometer(float, int)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x30): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Odometer(float, int)':
odometer_main.cpp:(.text+0x30): multiple definition of 'Odometer::Odometer(float, int)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x30): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Set_miles(int)':
odometer_main.cpp:(.text+0x72): multiple definition of 'Odometer::Set_miles(int)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x72): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Set_gallons(float)':
odometer_main.cpp:(.text+0x8a): multiple definition of 'Odometer::Set_gallons(float)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x8a): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Get_mpg()':
odometer_main.cpp:(.text+0xa8): multiple definition of 'Odometer::Get_mpg()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xa8): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Get_gallons()':
odometer_main.cpp:(.text+0xbc): multiple definition of 'Odometer::Get_gallons()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xbc): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Get_miles()':
odometer_main.cpp:(.text+0xd0): multiple definition of 'Odometer::Get_miles()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xd0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Add_trip(int, float)':
odometer_main.cpp:(.text+0xe0): multiple definition of 'Odometer::Add_trip(int, float)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xe0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Check_mileage(float)':
odometer_main.cpp:(.text+0x140): multiple definition of 'Odometer::Check_mileage(float)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x140): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Print_info()':
odometer_main.cpp:(.text+0x168): multiple definition of 'Odometer::Print_info()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x168): first defined here
collect2: error: ld returned 1 exit status
makefile:2: recipe for target 'odometer' failed
make: *** [odometer] Error 1
In short, replace #include "odometer.cpp" with #include "odometer.hpp". Now for the why.
Your program consists of source files like main.cpp and odometer.cpp. These files contain definitions for functions, variables, or classes in your project. Your compiler compiles each source file (.cpp) separately into object files (.o), and then your linker links these object files together to form your program.
However, although your source files are compiled separately, they will need to interact with each other. main.cpp will want to create Odometer objects and access Odometer member functions and so on. So we need a way to tell main.cpp what an Odometer is. The easiest way to do that is to define Odometer in a header file, and #include that header in main.cpp.
#include is a preprocessor directive that inserts the contents of another file into the current file. The preprocessor runs before your code is actually compiled. The idea is that you have some declarations in a file, which we call a header file, and multiple source files that need access to those declarations. So each source file will #include the header.
Note though that main.cpp doesn't need access to the definitions of Odometer's member functions, it just needs to know what those functions are and how to call them. That information is in the class definition in odometer.hpp, not in odometer.cpp. It would be an error to #include "odometer.cpp", because then we would have functions that are defined in two different places, and the linker will complain.
So in general you put your class definition in a header file (.hpp), put the class implementation in a source file (.cpp), and #include the header file in any other source file that needs access to that class. If you structure your programs correctly in this way, you should never need to #include a .cpp file into another .cpp file.
The are multiple problems here:
odometer.hpp
Odometer(float g, int m): This is not defined in odometer.cpp
Odometer() : This default constructor should also be defined in odometer.cpp
Odometer has three member variables but only two are taken as input, it is unclear how the third mpg is initialized
There are no include guards in your header file
#ifdef ODO_H
#define ODO_H
class Odometer{
// your class declaration
};
#endif
odometer.cpp
#include "odometer.hpp"
#include <iostream> - since you are using std::cout
Provide definitions for various Odometer constructors.
main.cpp
#include "odometer.hpp" - since you are using Odometer class here
Solving these issues should help you compile your code.
If you are including your odometer.cpp into your odometer_main.cpp, you can't also compile separately your odometer.cpp and link it with your odometer_main.cpp. In that case, yeah, you will get duplicate symbols. The typical way, though, is to only include the .hpp file into your main, and all else should compile and link fine.
It is important to used file exclusion directives to avoid multiple inclusion.
#ifndef ODOMETER_H
#define ODOMETER_H
#include "odometer.h"
#endif
Have a look at this question:
Why are #ifndef and #define used in c++ header files
Also as the guys commented, you should include the h file
is it possible to have 2 (or more) different implementations for the same function declared in a header file?
I'll give an example - let's say we have a header file called common.h and 2 source files called src1.c and src2.c.
common.h
//lots of common function declarations implemented in some file common.c
int func(int a, int b);
src1.c
#include "common.h"
int func(int a, int b)
{
return a+b;
}
src2.c
#include "common.h"
int func(int a, int b)
{
return a*b;
}
let's say that I want each of the source file to use its local version of func(). is it possible to do so?
Yes, but if you attempted to link your main program against both src1 and src2 you would encounter an error because it wouldn't know which definition to use.
Headers are just ways for other code objects to be aware of what's available in other objects. Think of headers as a contract. Contracts are expected to be filled exactly one time, not zero or multiple times. If you link against both src1 and src2, you've essentially filled the int func(int a, int b); contract twice.
If you need to alternate between two functions with the same signature, you can use function pointers.
If you want each source file to only use its local implementation of func, and no other module uses those functions, you can remove the declaration from the header and declare them as static.
src1.c
static int func(int a, int b)
{
return a+b;
}
src2.c
static int func(int a, int b)
{
return a*b;
}
By doing this, each of these functions is only visible in the module it is defined in.
EDIT:
If you want two or more functions to implement an interface, you need to give them different names but you can use a function pointer to choose the one you want.
common.h
typedef int (*ftype)(int, int);
int func_add(int a, int b);
int func_mult(int a, int b);
src1.c
#include "common.h"
int func_add(int a, int b)
{
return a+b;
}
src2.c
#include "common.h"
int func_mult(int a, int b)
{
return a*b;
}
Then you can chose one or the other:
ftype func;
if (op=='+') {
func = func_add;
} else if (op=='*') {
func = func_mult;
...
}
int result = func(value1,value2);
If you compile it with each src[x].c, you'll be able to use it in any function of your .c
You can decide to not expose the function implementation to other translation units. In c, use keyword static before the function signature right where you implement the function (see code below); In C++, you can also use unnamed namespaces. By doing so, the linker will not give you an error, and each translation unit will use it's own implementation:
Suppose the following two translation units main.c and another.c. Both have their (private) implementation of int function(a,b), such that they yield different results when calling it:
extern void someOtherFeature();
static int function (a,b) {
return a+b;
}
int main(){
int x = function(1,2);
printf("main: function(1,2)=%d\n", x);
someOtherFeature();
}
// another.c:
#include <stdio.h>
static int function (a,b) {
return a*b;
}
void someOtherFeature() {
int x = function(1,2);
printf("someOtherFeature: function(1,2)=%d\n", x);
}
Output:
main: function(1,2)=3
someOtherFeature: function(1,2)=2
However, if both translation units exposed their implementations (i.e. both omitted keyword static, then the linker would report an error like duplicate symbol _function in:....
If you want each source file to use a local version of func, just put it in an unnamed namespace:
For example src1.C:
namespace
{
int func(int a, int b)
{
return a+b;
}
}
Then each source file will use its own version. You don't need to declare it in the header.
Note that your original code with the definitions at global namespace and declared in the header violates the one definition rule (two function definitions for the same name must always have the same definition), invoking undefined behavior, no diagnostic required.
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 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