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
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);
I'm comparatively new to C++ so I tested some things out in Xcode, and found a really weird thing.
This is my 'Testing.h' file
#ifndef Testing_h
#define Testing_h
class Testing{
private:
int a;
public:
Testing(int a=3);
void hey(int b);
};
#endif
This is my 'Testing.cpp' file
#include "Testing.h"
Testing::Testing(int a){
a = 4;
}
And finally, this is the 'main.cpp' file
#include <iostream>
#include "Testing.h"
using namespace std;
int main(){
Testing a;
//Apparently not completing the definitions of every abstract methods in the class is not a problem
}
I only declared 'void hey(int b)' in 'Testing.h' but have not defined it in 'Testing.cpp'. So I was wondering how it is possible for the compiler to successfully compile the 'main.cpp' without having enough information of 'void hey(int b)'. Thanks in advance!
Because you never require there to be a definition for hey().
You can require a definition by calling it, for example :
a.hey(42);
And you'll see that the linker isn't too happy because hey is an undefined reference.
Testing a;//Apparently not completing the definitions of every abstract methods in the class is not a problem
You defined constructor with default value a=3 but calling both constructor argument and class parameter the same name is bad practice.
Instead you can write this:
//Testing.h
#ifndef Testing_h
#define Testing_h
using namespace std;
class Testing{
private:
int number;
public:
Testing(int a=3): number(a = 4){}//it's the same as your implementation in cpp file
void hey(int b);
int getNumber() {return number;}
};
#endif
//main.cpp
#include <iostream>
#include "Testing.h"
int main()
{
Testing object;
cout<<object.getNumber();// returns 4
return 0;
}
And why hey compiles?
During building your project compiler translates your source code into object code by verifying the syntax. After that process linker checks the definitions marked by whole phrases. Source code is compiled from each file provided. Linker doesn't care for the implementation presence, it only looks it up if a method is used by the program. So even without implementation of hey your program compiles.
Last remark
It's discouraged to include .cpp files use headers instead. Sometimes you can get yourself into multiple definitions of the same functions causing compiler errors.
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.
I am trying to declare the functions in separate files. In the code given below, my main() is defined in main.cpp and the int addition(int x, int y) is defined
in an another file named function.cpp.
My code:
main.cpp
#include "function.cpp"
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int b = 15;
int sum = addition(a,b);
cout<<"\nSum = "<<sum<<"\n";
return 0;
}
fucntion.cpp
int addition(int x, int y)
{
int sum = x + y;
return sum;
}
But by using the above cod in Eclipse i am getting the following error. On the other hand, if i compile the code manually using make
through the linux terminal then, the same got works.
ERROR:
/home/eclipse_workspace/multiFiles/Debug/../funtion.cpp:9: multiple definition of `addition(int, int)'
./funtion.o:/home/eclipse_workspace/multiFiles/Debug/../funtion.cpp:9: first defined here
collect2: ld returned 1 exit status.
First of all it is not recommended to include .cpp files. You should create header (.h) with declarations, put implementations to .cpp, like now and wherever you need to use it just include.h . You should also read about avoiding multiple includes by adding #ifndef/#define/#endif.
Update:
#include works in pre compiling phase and more or less it means "paste here what you have in file ...". So it copies function from one file and pastes to main file then compiles it. After this it compiles also cpp file with your function - also ok. Now comes linking: because of previous steps and copy-paste it has two definitions (actually two symbols) which has same name - that is causing the error and that's why we have headers :)
First create a header file, for example Addition.h and declare the function name inside it. Then make a file Addition.cpp and write the addition function implementation and then include the Addition.h in your main.cpp file.
The concept of using a header file is that you can use it anywhere else and is not limited to your main.cpp program file.
So, in short
Addition.h
class Addition { public:
int addition(int a , int b); //function declaration
private: int result_; };
then in Addition.cpp
#include Addition.h
int Addition::addition(int x, int y) {
// function implementation
}
in main.cpp
#include <Addition.h>
int main()
{ int a=3, b=4, sum=0;
Addition objAdd; //creation of object for class Addition
sum = objAdd.addition(a,b);
}
Hope this helps in structuring your code.
My function test is added to two different .cpp-files and the functions are private to their respective files as shown below
test1.cpp
#include <iostream>
using namespace std;
void test()
{
cout << "test" << endl;
}
test2.cpp
#include <iostream>
using namespace std;
void test()
{
cout << "test" << endl;
}
main.cpp
#include <iostream>
using namespace std;
int main()
{
return 0;
}
During linking I get the error multiple definition of test() - but how is that possible, considering that the two files have their own private scope!? I could understand it if I included the function prototype in each .cpp-files' corresponding header, but there is no such thing in this example.
You need the inline keyword for that:
inline void test()
{
cout << "test" << endl;
}
This allows you to have multiple definitions in separate source files without violating the one-definition rule. However, note that the function still has external linkage and they will all resolve to the same address. Also:
An inline function shall be defined in every translation unit in which
it is odr-used and shall have exactly the same definition in every
case
If you want separate functions with different addresses (internal linkage), use the static keyword instead.
Both test functions are in the same global namespace of the program. In order to avoid error you may:
1) wrap any or both functions in namespace:
namespace A
{
void test()
{
...
}
}
2) use static keyword
3) just rename one of them
Add static in each test function.
#include <iostream>
using namespace std;
static
void test()
{
cout << "test" << endl;
}
To elaborate on above answers:
In C++, function declarations can be repeated as many times as you want. A function definition however (i.e. the function body), can occur only once.
When creating your binary, the compiler compiles each file to a obj file so in your example you end up with test1.obj, test2.obj and main.obj. After all files compiled successfully, the linker links them together to create your executable. This is where multiple definitions for the same function are found and why linking fails.
Depending on what you want, you can do the following to resolve this:
If you want multiple different functions with the same name, then you have to disambiguate them. C++ wouldn't be C++ if you only had one way to do this:
The old c way: use the static keyword
Use an anonymous namespace
Use a namespace
If you want only one function:
Separate the definition from the declaration, i.e. put the declaration in a header file and move the definition to a source file.
Define the function as inline in a header