I'm making my first attempt at unit testing in C++, and I haven't used C++ in a number of years (I'm mainly a C# coder at the moment). It seems like I'm making a right pig's ear of it - I hope someone can steer me back onto the righteous path. I'm just getting started here and would really like to be implementing these tests using the best practice possible, so any and all comments are welcome, even though I'm most concerned with my linker error at present.
So, I have an overall solution "Technorabble", with sub-projects "CalibrationTool" and "CalibrationToolUnitTests".
CalibrationTool has a MathUtils.h file:
#ifndef __math_utils__
#define __math_utils__
#include "stdafx.h"
#include <vector>
namespace Technorabble
{
namespace CalibrationTool
{
double GetDoubleVectorAverage(std::vector<double> v)
{
double cumulativeValue = 0;
for(std::vector<double>::iterator iter = v.begin(); iter != v.end(); ++iter)
{
cumulativeValue += *iter;
}
return cumulativeValue / v.size();
}
}; // end namespace CalibrationTool
}; // end namespace Technorabble
#endif // !__math_utils__
(But no .cpp file as I was having all kinds of (somewhat similar) issues getting my template function working - so I ended up defining that inline).
Moving on to the Unit Tests project, I have a main.cpp:
#include "MathUtilsTest.h"
void RunMathUtilsTests();
int main()
{
RunMathUtilsTests();
// Other class tests will go here when I have things to test
}
void RunMathUtilsTests()
{
MathUtilsTest* mathUtilsTest = new MathUtilsTest();
mathUtilsTest->RunTests();
delete mathUtilsTest;
}
Finally, the header and cpp for the MathUtilsTest class, again, fairly simple:
.h:
#ifndef __MATH_UTILS_TEST__
#define __MATH_UTILS_TEST__
#include "CalibrationToolUnitTestsLogging.h"
#include "..\CalibrationTool\MathUtils.h"
class MathUtilsTest
{
public:
MathUtilsTest();
~MathUtilsTest();
bool RunTests();
private:
bool GetDoubleVectorAverageTest();
}; // end class MathUtilsTest
#endif
.cpp:
#include "MathUtilsTest.h"
#include <sstream>
bool MathUtilsTest::RunTests()
{
return GetDoubleVectorAverageTest();
}
MathUtilsTest::~MathUtilsTest()
{
}
MathUtilsTest::MathUtilsTest()
{
}
bool MathUtilsTest::GetDoubleVectorAverageTest()
{
bool passed = true;
std::vector<double> values;
for (int i = 1; i < 23; i++)
{
values.push_back(i);
}
// vector becomes: 1, 2, 3, 4, .....20, 21, 22. Average is 11.5
double expectedAverage = 11.5;
double calculatedAverage = Technorabble::CalibrationTool::GetDoubleVectorAverage(values);
if (calculatedAverage != expectedAverage)
{
std::ostringstream s;
s << calculatedAverage;
std::string avgString = s.str();
CalibrationToolUnitTestsLogging::Write("Failed MathUtilsTest.GetDoubleVectorAverageTest: " + avgString);
passed = false;
}
else
{
CalibrationToolUnitTestsLogging::Write("Passed MathUtilsTest.GetDoubleVectorAverageTest");
}
return passed;
}
This all seemed fine to me, I'm protecting my header with #ifndef, etc. But I'm still getting the following errors:
1) error LNK1169: one or more multiply defined symbols found
2) error LNK2005: "double __cdecl Technorabble::CalibrationTool::GetDoubleVectorAverage(class std::vector >)" (?GetDoubleVectorAverage#CalibrationTool#Technorabble##YANV?$vector#NV?$allocator#N#std###std###Z) already defined in main.obj C:_SVN\Technorabble\Windows Software\CalibrationToolUnitTests\MathUtilsTest.obj
How can this be? Can anyone spot where it's going wrong?
Functions defined in headers should be marked as inline:
inline double GetDoubleVectorAverage(std::vector<double> v)
{
}
If it's longer than a couple of lines, consider moving it to an implementation file.
pragmas or include guards don't protect against multiple definitions.
Note that you should pass v by const reference rather than by-value.
You are defining a function GetDoubleVectorAverage in a header. This means that it will be defined in every translation unit (i.e. every source file) that includes that header. If your program contains more than one such translation unit, then you'll have more than one definition - which isn't allowed.
Solutions are:
Add inline to the function definition, to relax this rule and allow multiple identical definitions; or
Move the function definition into a source file, and only declare it in the header.
I'm protecting my header with #ifndef
That only prevents the header from being included more than once within the same translation unit. It doesn't prevent inclusion from more than one unit.
Also, you shouldn't use a reserved name like __math_utils__ as a header guard, even if the internet is littered with examples of dodgy code doing that.
I was having all kinds of (somewhat similar) issues getting my template function working
Templates usually need to be defined in header files, to make the definition available at the point of use. Function templates are implicitly inline, but normal functions (like this one) aren't.
Related
I encountered this problem when I try to compile my code
I thought it might be caused by header files including each other. But as far as I can tell I did not find any issues with my header files
Error LNK1169 one or more multiply defined symbols
found Homework2 D:\05Development\04 C_C++\C\DS Alg
class\Homework2\Debug\Homework2.exe 1
also, there's an error telling me that function Assert() has been declared elsewhere.
Error LNK2005 "void __cdecl Assert(bool,class
std::basic_string,class
std::allocator >)"
(?Assert##YAX_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
already defined in DataBase.obj Homework2 D:\05Development\04
C_C++\C\DS Alg class\Homework2\Homework2\dbTest.obj 1
here's the structure of my code:
function
void Assert(bool val, string s)
{
if (!val)
{
cout << "Assertion Failed!!: " << s << endl;
exit(-1);
}
}
is in Constants.h
A virtual class List includes Constants.h
#pragma once // List.h
#include "Constants.h"
An array list includes List class, in the AList class it calls the Assert function
#pragma once //AList.h
#include "List.h"
...
Assert((pos >= 0) && (pos < listSize), "Position out of range");
In the DataBase class I created a AList member
private:
AList<CData> set;
header looks like this:
#pragma once
#include "AList.h"
#include "CData.h"
and CData.h looks like this:
#pragma once
class CData
{
private:
std::string m_name;
int m_x;
int m_y;
public:
CData(std::string str = "null", int x = 0, int y = 0) : m_name(str), m_x(x), m_y(y) {}
// Helper functions
const std::string& GetName() const { return this->m_name; }
const int& GetX() const { return this->m_x; }
const int& GetY() const { return this->m_y; }
};
When you build your project, each .cpp file gets compiled separately into different object files. The once in #pragma once only applies to the compilation of a single .cpp file, not for the project as a whole. Thus if a .cpp file includes header A and header B, and header B also includes header A, then the second include of header A will be skipped.
However, if you have another .cpp file that includes A, A will be included in that object file again -- because #pragma once only works when compiling a single .cpp file.
An #include statement literally takes the content of the included file and "pastes" it into the file that included it. You can try this by looking at the output of the C preprocessor tool (cpp in the gcc toolchain). If you are using the gcc toolchain, you can try something like this to see the file after its includes have been applied:
cpp file.cpp -o file_with_includes.cpp
If you have a function in your header, like Assert in your example, the function gets replicated into each .cpp file you include it in.
If you have A.cpp and B.cpp, that both include your Constants.h file, each object file (.o or .obj depending on your environment) will include a copy of your Assert function. When the linker combines the object files to create a binary, both object files will declare that they provide the definition for Assert, and the linker will complain, because it doesn't know which one to use.
The solution here is either to inline your Assert function, like this:
inline void Assert(bool val, string s)
{
if (!val)
{
cout << "Assertion Failed!!: " << s << endl;
exit(-1);
}
}
or to provide its body in its own .cpp file, leaving only the function prototype in the header.
Constants.h:
void Assert(bool val, string s);
Constants.cpp:
void Assert(bool val, string s)
{
if (!val)
{
cout << "Assertion Failed!!: " << s << endl;
exit(-1);
}
}
Mind you, the Standard Library also offers assert(), which works nicely too. (see https://en.cppreference.com/w/cpp/error/assert).
#include <cassert>
...
assert(is_my_condition_true());
assert(my_variable > 23);
// etc..
Just keep in mind that the assert declared in cassert only works when compiling for Debug, and gets compiled out when building for Release (to speed up execution), so don't put any code in assert that has side effects.
#include <cassert>
...
// Don't call functions with side effects.
// Thus function decreases a "count" and returns the new value
// In Release builds, this line will disappear and the decrement
// won't occur.
assert(myclass.decrement_count() > 0);
There are a lot of similar questions on Stack Overflow, regarding this topic.
I am creating a project with multiple files (.cpp and .h). I am getting the error:
C2011: 'Render': 'class' type redefinition
I have read about it. Some people are saying use guards, so I am using #pragma once on all header files. Some people say the header is being included multiple times, but the guards will prevent that. So what am I doing wrong?
Code:
Cubes.h
#pragma once
char orientation(int sides, int hV);
std::vector<char> visOrd(std::string *xOrd, int *pov, int ord);
std::vector<int> convertColour(std::vector<std::string> rlBoxCol);
std::tuple<std::vector<int>, std::vector<std::string>> organiseLayers(std::vector<int> boxCoords, std::vector<std::string> rlBoxCol, std::vector<float> rot);
class Render
{
private:
std::vector<float> rot;
std::vector<int> boxCoords;
std::vector<std::string> rlBoxCol;
int gridSize;
int cubeSize;
std::vector<int> offset;
public:
Render();
void setRotation(std::vector<float> setRot);
std::vector<float> getRotation();
void setCoordinates(std::vector<int> setBoxCoords);
std::vector<int> getCoordinates();
void setColours(std::vector<std::string> setRlBoxCol);
std::vector<std::string> getColours();
void setSizeOfGrid(int setGridSize);
int getSizeOfGrid();
void setSizeOfCubes(int setCubeSize);
int getSizeOfCubes();
void setOffset(std::vector<int> setOffset);
std::vector<int> getOffset();
void display();
};
Cubes.cpp
#include "Cubes.h"
#include "Global.h"
char orientation(int sides, int hV)
{
// Code
}
std::vector<char> visOrd(std::string *xOrd, int *pov, int ord)
{
// Code
}
std::vector<int> convertColour(std::vector<std::string> rlBoxCol)
{
// Code
}
std::tuple<std::vector<int>, std::vector<std::string>> organiseLayers(std::vector<int> boxCoords, std::vector<std::string> rlBoxCol, std::vector<float> rot)
{
// Code
}
Render::Render()
{
this->rot;
this->boxCoords;
this->rlBoxCol;
this->gridSize;
this->cubeSize;
this->offset;
}
void Render::setRotation(std::vector<float> setRot)
{ // Set rotation
rot = setRot;
}
std::vector<float> Render::getRotation()
{ // Get rotation
return rot;
}
void Render::setCoordinates(std::vector<int> setBoxCoords)
{
boxCoords = setBoxCoords;
}
std::vector<int> Render::getCoordinates()
{
return boxCoords;
}
void Render::setColours(std::vector<std::string> setRlBoxCol)
{
rlBoxCol = setRlBoxCol;
}
std::vector<std::string> Render::getColours()
{
return rlBoxCol;
}
void Render::setSizeOfGrid(int setGridSize)
{
gridSize = setGridSize;
}
int Render::getSizeOfGrid()
{
return gridSize;
}
void Render::setSizeOfCubes(int setCubeSize)
{
cubeSize = setCubeSize;
}
int Render::getSizeOfCubes()
{
return cubeSize;
}
void Render::setOffset(std::vector<int> setOffset)
{
offset = setOffset;
}
std::vector<int> Render::getOffset()
{
return offset;
}
void Render::display()
{
// Drawing code
}
EDIT:
I have now changed the code in ways you said. Now I am getting errors LNK2005 and LNK1169. What's gone wrong now?
EDIT 2: (Errors)
LNK2005
"class sf::RenderWindow Window" (?Window##3VRenderWindow#sf##A) already defined in Cubes.obj
C:\Users\George\Documents\C++\Projects\Don't fall\Don't fall\main.obj 1
.
LNK2005
"class std::basic_string,class std::allocator > status" (?status##3V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A) already defined in Cubes.obj
C:\Users\George\Documents\C++\Projects\Don't fall\Don't fall\main.obj 1
.
LNK1169
one or more multiply defined symbols found
C:\Users\George\Documents\C++\Projects\Don't fall\Debug\Don't fall.exe 1
Global.h:
#pragma once
#include <SFML\Graphics.hpp>
// This is where all my global variables will be
extern sf::RenderWindow Window(sf::VideoMode(500, 500), "Maximize window to play the game");
extern std::string status = "NULL";
Your Cubes.cpp does redefine the class Render. In general the .h file has the class prototype and the .cpp defines the methods.
Try adding this to the top of the Cubes.cpp:
#include "Cubes.h"
removing this from the top of Cubes.cpp:
class Render
{
private:
std::vector<float> rot;
std::vector<int> boxCoords;
std::vector<std::string> rlBoxCol;
int gridSize;
int cubeSize;
std::vector<int> offset;
public:
and removing this from the bottom:
};
This is not how you provide the implementation of a class in C++. The keyword class defines the class, which is what you have in your header (.h file). In the .cpp file you wish to implement the methods which you defined in your header file, so you should not redefine the entire class. Rather, you need to provide implementations for the methods (member functions) of the class, like so:
void Render::setRotation(std::vector<float> setRot)
{ // Set rotation
rot = setRot;
}
std::vector<float> Render::getRotation()
{ // Get rotation
return rot;
}
Notice the prefix Render::? This is how you indicate that you are providing an implementation for the function setRotation of the class Render. Just add the function implementation like this in your cpp, do not nest them within a class, do not include any fields (the member fields have already been defined in the header, they are done).
Update:
OK, so according to the updated answer your linker error refers to the instances sf::RenderWindow Window and std::string status; this error occurs when linking main.obj (from main.cpp?) with Cubes.obj. The error is telling you that both main.obj and Cubes.obj define these variables.
I recommend that you read about "Compilation Units" in C++ and difference between declaration and definition of a symbol; but to give a very brief summary:
Essentially, the compiler runs on a single "compilation unit"; you can think of it as a single file. What the #include-statement does is basically copy/paste the content of the included file into the compilation unit. So when you compile Cubes.cpp, it will go through all of the nested includes until it has generated one huge cpp-file with everything included. Then it will build this into an .obj file. Then you do the same thing with main.cpp, and any other .cpp files you might have. Finally, the linker will attempt to link these object files together to produce the final result.
Now, if the linker finds duplicate definitions when linking two objects you will get an error. So you cannot have two global variables with the same name! If both Cubes.cpp and main.cpp include global.h, then both compilation units contain global variable definitions Window and status. This is causing your linker error.
This is why you put a declaration in the header (since it is included in multiple compilation units), and the definition in the source file (typically not included elsewhere). You build the source file to produce the only object file containing the definition; all other object files only reference the declaration. The linker can then link those references to the definition found in one the object files.
So you want to declare the variables in the header, and move the definition somewhere else. For instance, to main.cpp; but that depends entirely on the rest of your application and what you are trying to achieve. Outside the scope of the question.
This question already has answers here:
error: Class has not been declared despite header inclusion, and the code compiling fine elsewhere
(9 answers)
Closed 7 years ago.
You could have forgot to include problemclass.h from the file where you are using ProblemClass.
You could have misspelled the name of ProblemClass either in its own header file or in the place where you are using it. This can be
hard to spot if it is a capitalization error such as writing
Problemclass or problemClass instead of ProblemClass.
You could have copy-pasted your inclusion guard #defines from one header file to another and then forgot to change the defined names.
Then only the first of those two included header files would take
effect.
You could have placed ProblemClass in a namespace A, in which case you must refer to ProblemClass as A::ProblemClass if you are referring
to it from outside the namespace A.
You may be using templates and not expecting two-phase lookup to work the way it does.
You could have misspelled the file name in your include. The compiler would not report an error on that if you also have an old
version of that file under the misspelled name.
You could have made ProblemClass a macro that only gets defined after you include problemclass.h, in which case what you see as
ProblemClass gets replaced by something else by the macro
preprocessor.
You could have defined ProblemClass in a header file other than problemclass.h and then problemclass.h actually defines something
else.
The above was taken from another similar question, I found the points useful but none actually solved my problem, stated hereunder:
I'm creating a natural language processor for a robot, giving the software various objects to represent real world items in its environment (Blocks world for now), one of the objects defined in Block:
/*
* Block.h
*
* Created on: 11 Mar 2015
* Author: Edward
*/
#ifndef BLOCK_HPP_
#define BLOCK_HPP_
#include "typedefinitions.h"
#include "dynamixel.h"
#include "BasicRobotFunctions.hpp"
class Block {
public:
bool grounded;
//TODO position is a deprecated variable, replace with distance from
//pos position;
int number;
int distance;
int object_brightness;
Block(BasicRobotFunctions basic);
virtual ~Block();
void setBrightness(int brightness);
void setGrounded(bool ground);
//void setPosition(int x, int y);
void setDistance(int number);
void setNumber(int number);
//pos getPosition();
int getNumber();
int getDistance();
bool getGrounded();
int getBrightness();
int lookAround(BasicRobotFunctions basic);
};
#endif /* BLOCK_H_ */
with source file:
/*
* Block.cpp
*
* Created on: 11 Mar 2015
* Author: Edward
*/
#include "Block.hpp"
#define DEFAULT_PORTNUM 3 // COM3
#define DEFAULT_BAUDNUM 1 // 1Mbps
Block::Block(BasicRobotFunctions basic) {
grounded = false;
number = Block::lookAround(basic);
}
Block::~Block() {}
void Block::setGrounded(bool ground){
grounded = ground;
}
/*
void Block::setPosition(int x, int y){
position.x = x;
position.y = y;
}*/
void Block::setDistance(int dist){
distance = dist;
}
void Block::setNumber(int num){
number = num;
}
bool Block::getGrounded(){
return grounded;
}
/*
pos Block::getPosition(){
return position;
}*/
int Block::getNumber(){
return number;
}
int Block::getDistance(){
return distance;
}
int Block::getBrightness(){
return object_brightness;
}
//TODO Arrange function to incorporate Turn() in BasicRobotFunctions
int Block::lookAround(BasicRobotFunctions basic){
int num = 0;
dxl_initialize(DEFAULT_PORTNUM,DEFAULT_BAUDNUM);
for(int i = 0;i<360;i++){
dxl_write_word(11,32,-255);
dxl_write_word(11,30,200);
basic.Step(1);
dxl_write_word(11,32,255);
dxl_write_word(11,30,100);
if(dxl_read_byte(100,32) >= dxl_read_byte(100,52)){
num++;
}
}
dxl_terminate();
return num;
}
void Block::setBrightness(int bright){
object_brightness = bright;
}
I am however receiving the following compilation error from the constructor and from the turnAround(BasicRobotFunctions) method:
In file included from Robot.hpp:11,
from BasicRobotFunctions.hpp:12,
from main.cpp:8:
Block.hpp:23: error: expected `)' before 'basic'
Block.hpp:35: error: 'BasicRobotFunctions' has not been declared
make.exe: *** [main.o] Error 1
Having checked my other classes utilizing objects as variables I get the same error.
In response to the points in the quote:
- BasicRobotFunctions.hpp is included
- the class name is spelt the same in all different instances mentioning it
- I didn't copy paste any inclusion guard
- I didn't use any namespaces in the project
- Nor am I using any templates
- the file name isn't misspelled in my include
- I haven't defined any macros in the program
- I made sure every class was defined in its own header file
Is there any other issue my system could possibly have, any mistake I'm making or simply anything I'm doing which is bad programming practice here?
The cause of your problem:
You have a header file circular dependency problem.
main.cpp includes BasicRobotFunctions.hpp
which includes Robot.hpp
which includes Block.hpp
which includes BasicRobotFunctions.hpp.
If your header files are properly guarded against multiple inclusion (which it seems that they are), Block.hpp won't see the definitions of BasicRobotFunctions.hpp because it is already in the middle of including it.
How to spot the problem:
The source of this problem is apparent in the compilation error message and in your Block.hpp file.
The compiler is reporting an error in Block.hpp, and it is describing line by line how it got to that file via inclusions. The source to your Block.hpp file makes it clear that it is trying to include BasicRobotFunctions.hpp.
The fix:
In your case, you can modify your method signatures in Block.hpp to use a (perhaps constant) reference to the BasicRobotFunctions type, and then forward declare the type. This allows you to eliminate the dependency on the BasicRobotFunctions.hpp header file. (Block.cpp would likely need to include both Block.hpp and BasicRobotFunctions.hpp.)
//...
#include "typedefinitions.h"
#include "dynamixel.h"
class BasicRobotFunctions; // Forward declaration
//...
Block(const BasicRobotFunctions &basic);
//...
int lookAround(const BasicRobotFunctions &basic);
//...
You may be able to avoid this problem in the future by minimizing what headers are required to allow your header file to compile. This means your header file should:
Use forward declarations to types that are used.
Use references to forward declared types.
You can check that your header file has minimized its dependencies by making sure it compiles by itself. I accomplish this by including the header file first in a corresponding source file, and then make sure the source file compiles.
// Foo.cpp
#include "Foo.hpp"
//...
Well you can put a forward declaration before the class as
class BasicRobotFunctions;
class Block {
public:
bool grounded;
//TODO position is a ...
but this kind of error means that the #include "BasicRobotFunctions.hpp"
don't declare the BasicRobotFunctions. It's possible a trouble with code guards?
The circular inclusion can be solved using the forward declaration, putting correct guards in headers and moving some includes to source files.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have a trouble with finding answer for my questions (Q), so I registered here to ask you guys how it really works (or don't works) ;)
I am writing in c++, in Visual Studio 2012, but still don't really know how it is with #includes, namespaces etc. in header files. Do I even need to use them?
(Q1): Let's say I have one .cpp file and few .h files, which are using, for example: vectors, things from <algorithm>, <ctime> and some other libraries, but I do not write #include <something> in header files, only in .cpp. Is it correct? Or should I include everything I use in every header?
Usually everything works for me, I can even say it always "works", because I don't have too much experience yet and I was usually containing everything in one .cpp and 1 or 2 headers with some void functions. But don't know if it works because it should, or because, for example, mu compiler allows that and in some issues it can cause errors.
(Q2): Now a thing about using namespace std;
In some cases functions in .h files works without it, but sometimes not. For example, the voids that are working (just simple voids for merge-sort):
#ifndef LISTA_1_H
#define LISTA_1_H
#include "Lista_0_Zadanie_1.h"
void MERGE(vector<double> &A, int p, int q, int r)
{
int i = p;
int j = q+1;
int lenght = r - p + 1;
int k=0;
vector<double> merged;
merged.assign (lenght,0);
while((i<=q)&&(j<=r))
{
if(A[i] <= A[j])
{
merged[k]=A[i];
++i;
}
else
{
merged[k]=A[j];
++j;
}
k++;
}
if(j<=r)
{
while(j<=r)
{
merged[k]=A[j];
++j;
++k;
}
}
if(i<=q)
{
while(i<=q)
{
merged[k]=A[i];
++i;
++k;
}
}
for (i=0;i<lenght;++i)
A[p+i]=merged[i];
}
void MERGESORT(vector<double> &A, int k, int l)
{
if(k<l)
{
int m = (k+l)/2;
//int mp = m+1;
// cout << "koza"<<endl;
MERGESORT(A,k,m);
MERGESORT(A,m+1,l);
MERGE(A,k,m,l);
}
}
void TRIPLE_MERGESORT(vector<double> &A, int k, int l)
{
if(k<l)
{
int one_third = (l-k)/3;
int two_third = 2*(l-k)/3; // k < k+one_third < k+two_third < l
TRIPLE_MERGESORT(A,k,k+one_third);
TRIPLE_MERGESORT(A,k+one_third+1,k+two_third);
TRIPLE_MERGESORT(A,k+two_third+1,l);
MERGE(A,k,k+one_third,k+two_third);
MERGE(A,k,k+two_third,l);
}
}
void INSERT_MERGESORT (vector<double> &A, int k, int l)
{
if(l<19) // l=n-1, więc n<20 <=> l < 19
{
double y;
int i,j;
for(i=0; i<l+1; ++i)
{
y = A[i];
j = i-1;
while((j>=0) && (A[j]>y) )
{
A[j+1] = A[j];
--j;
}
A[j+1]=y;
}
}
else
MERGESORT(A,k,l);
}
#endif
... and in some cases it does not work, if I do not write "using namespace std;" or add " std:: " in correct place (here before vectors), it does not work:
#ifndef SCHEMAT_HORNERA_H
#define SCHEMAT_HORNERA_H
//using namespace std;
void HORNER( int n, double z0, double p_z0, vector<double> a, vector<double> &B)
{
B[n] = a[n];
for(int k = n-1; k>=0; --k)
{
B[k] = a[k] + z0*B[k+1];
}
}
#endif
So here's my question: Should I always use "std::" or "using namespace std"?
If yes, why are my files until now "working"? Because in some cases VS allows for that, while it is not correct and some compilers and not allow for this?
Q1) Whether or not you need to #include a header with a full definition depends on if you need a full definition, or if just a forward-declare will do. In the case of needing just a forward-declaration, all you need to tell the compiler is the name of something. An example is if you need a pointer-to-something:
// fw-decl Foo
class Foo;
// define Gizmo
class Gizmo
{
public:
void DoIt();
Foo* mFoo; // just need a pointer, so don't need a full definition of foo
};
Later you will need a full definition if you actually use the Foo object, as with:
#include "foo.h"
#include "gizmo.h"
void Foo::DoIt()
{
mFoo->DoSomething(); // now we need a full definition
}
On the other hand, if the compiler needs to know for example how big Foo is, then you need a full definition.
#include "foo.h"
class Gizmo
{
public:
Foo mFoo; // need a full definition here
};
As a general rule of thumb, it is best to provide full definitions only when necesarry, so as to keep compilation times as quick as possible.
Q2) Simplified rule-of-thumb: never using namespace std. If you simply follow this rule of thumb without ever thinking about it, you will never have problems with namespace collisions, polluting the global namespace, or other nastiness.
Of course, this rule of thumb is a little over-simplified for those who actually think for a living, so here's a slightly better one:
1) Never using namespace in a header
2) Never using namespace in a source file unless it's your own namespace you're implementing.
Rules of thumb can be overly restrictive, and this is no exception, but it will get you on your way without venturing too far in to a landmine. The problem with using anmespace is it brings whatever is in that namespace in to global scope. Suppose you have your own header file:
mystring.h
namespace MyString
{
class string
{
// ...
};
}
...and then in the source file:
#include "mystring.h"
#include <string>
using namespace MyString;
using namespace std;
string s; // OOPS: which "string" is this? MyString::string, or std::string?
This ambiguity is obvious here, but int he real world it can be much less obvious, and result in some very hard-to-detect bugs.
(Q1) It is important to remember what an include declaration actually does. Basically it is nothing more than a simple copy/paste of the entire file which is being included in the new file.
Since header files are included in many places, it is generally frowned upon to have many unnecessary includes in .h files (unless using templates). In general, do not include in a header file when a forward declaration will suffice.
In the .cpp file, include ALL files necessary so that the program can compile.
Because you are using visual studio, you must be careful because it is very lenient on including files from the standard library that you actually forgot to include, and you may experience problems compiling on other systems.
(Q2) In a header file you should not have a "using" statement. Remember that the include statement is a simple copy/paste; so for that reason if you have a using statement it will be included in the new file as well.
In .h files you should always use std::vector, std::set, etc.
In .cpp files, it is ok to have using namespace std, using std::vector, etc.
(Sidebar) Related to your code, you should split it up into header files and cpp files. Do not have the definition in the .h file, only the declaration. Make a .cpp file and define the algorithm in there. Also do not have define guards in a .cpp file. Never include a .cpp file!
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; }