I'm learning C++ and currently trying to create a very basic class representing a boat's length and weight... It seems I'm running into problems trying to split it into header and cpp files.
These are the simple files I'm working with...
Boat.h:
#ifndef BOAT_H_
#define BOAT_H_
class Boat{
public:
Boat();
Boat(int,int);
private:
int length;
int weight;
};
#endif /* BOAT_H_ */
Boat.cpp:
#include "Boat.h"
Boat::Boat(){
length = 25;
weight = 2500;
}
Boat::Boat(int newLength, int newWeight){
length = newLength;
weight = newWeight;
}
When compiling, I get errors in Boat.cpp about it being "first defined here". I've been following tutorials and trying to do like they do but I just can't seem to get this right. Here is the full error message. What am I missing?
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:4: multiple definition of `Boat::Boat()'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:4: first defined here
Boat.o: In function `Boat':
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:4: multiple definition of `Boat::Boat()'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:4: first defined here
Boat.o: In function `Boat':
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:9: multiple definition of `Boat::Boat(int, int)'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:9: first defined here
Boat.o: In function `Boat':
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:9: multiple definition of `Boat::Boat(int, int)'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:9: first defined here
Edit :
I was including Boat.cpp in the main instead of Boat.h... Problem solved! Thank you!
There is no way to be sure what you did, but I did manage to generate your error with this main function:
#include "Boat.h"
#include "Boat.cpp"
int main(int argc, const char *argv[])
{
Boat b;
return 0;
}
compiled in the following way:
g++ -O0 -ggdb main.cpp Boat.cpp -o main
which results exactly in the error you reported. Whatever you did - you seem to have tried to include the Boat.cpp file twice, and by doing so, you have doubled the definition of your Boat class.
It seems that you included your boat.cpp file in the module where there is function main. You need to include only header boat.h in the module with main.
Related
This question already has answers here:
Separating class code into a header and cpp file
(8 answers)
Closed 5 months ago.
I don't know how to add functions of a class outside its scope to it, use them in another class and then compile it.
MyMain.cpp
#include"MyClass.cpp"
int main(){
MyClass myClass;
myClass.run();
}
MyClass.cpp
#ifndef MYCLASS_CPP
#define MYCLASS_CPP
#include<iostream>
class MyClass {
private:
void usage();
public:
void run();
};
void MyClass::usage(){
std::cout << "usage called" << std::endl;
}
void MyClass::run(){
usage();
}
#endif
I try to compile it with:
g++ MyMain.cpp MyClass.cpp -o main
With that I get the following error message:
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::usage()':
MyClass.cpp:(.text+0x0): multiple definition of `MyClass::usage()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x0): first defined here
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::run()':
MyClass.cpp:(.text+0x38): multiple definition of `MyClass::run()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x38): first defined here
collect2: error: ld returned 1 exit status
If I have understood the concept correctly, the function headers within the class serve only as placeholders. The actual functionality is then "overwritten" by the external functions, which also contain a body.
And why does the error message say, that the function is already defined in the MyMain.cpp?
I have also seen that there are many similar questions here, but unfortunately I could not expand my understanding of the basic problem to solve it.
Is it possible that I am using the command to build the class with C++ incorrectly or that I can save the #include "MyClass.cpp"?
Kind regards
Several things wrong. here's the steps to put it right
Rename MyClass.cpp to MyClass.h.
Create a new empty file MyClass.cpp
Move the function definitions MyClass::usage() { .. } and MyClass::run() { .. } from MyClass.h to MyClass.cpp. You should probably also move #include <iostream> but this is not essential.
Add #include "MyClass.h" to MyClass.cpp
Change #include "MyClass.cpp" to #include "MyClass.h" in MyMain.cpp
Then build as you are doing now. That part is correct.
Essentially the technique is to separate your code into declarations and definitions. The declarations go into header files, which are included in the cpp files. The cpp files contain the definitions and are what you compile.
I have been recently practicing managing multiple objects and drawing them in C++ using SFML library. I wanted my textures and future resources to be more reusable so I decided to make use of Thor library which suits my needs really well.
So I've written first few lines of code based on what you can find in this tutorial and the compiler always says:
main.cpp|12|error: 'textures_holder' does not name a type
This line gives an error :
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
I'm using Code::Blocks IDE with MinGW compiler and SFML 2.5.0.
Here's my main.cpp and the header file which contains extern object :
//...
#include <Thor/Resources.hpp>
#include "Dirt_Block.h"
using namespace std;
//Adding textures to the texture library
//THIS LINE GIVES AN ERROR
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
//Rest of code...
Dirt_Block.h (only the upper part) :
#ifndef DIRT_BLOCK_H
#define DIRT_BLOCK_H
#include <SFML\Graphics.hpp>
#include <vector>
#include <Thor/Resources.hpp>
#include <Thor/Resources/SfmlLoaders.hpp>
extern sf::Vector2u screenRes;
extern thor::ResourceHolder<sf::Texture, std::string> textures_holder;
//Rest of the code
I'd like to know what is causing this error and maybe help others who may experience similiar frustrating problems. Thanks for help.
EDIT :
As suggested in the comment I've declared a few extern int variables in the Dirt_Block.h so now it looks like this :
//...
extern int test_int_up;
extern sf::Vector2u screenRes;
extern thor::ResourceHolder<sf::Texture, std::string> textures_holder;
extern int test_int_d;
//...
And then assinged to them some value in main.cpp :
//...
test_int_up = 55;
test_int_d = 55;
//Adding textures to the texture library
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
//...
But the compiler gives error :
main.cpp|9|error: 'test_int_up' does not name a type
main.cpp|10|error: 'test_int_d' does not name a type
main.cpp|12|error: 'textures_holder' does not name a type
Much less distracting to see what your problem is without all the extraneous code!
C++ programs don't start from the top of the file and run code down to the bottom. They start at the main(), and control flow proceeds from there, with one thing triggering another.
(Note: That doesn't take into account global constructor ordering, which does go in order of declaration--but you have no guarantee of the order declarations from "different files" might run in.)
Point being, you can't just make random function or method calls in the middle of a file. That's where you put declarations. You have to be inside of a function or method to make calls, e.g.
int main() {
textures_holder.acquire(
"Dirt",
thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png")
);
...
}
[EDIT:]
The problem seems to belong to the functions, that take default-parameters. Without separating in *.h *.cpp and main file it worked as i implemented something like:
void foo(double db;); // deklaration
void foo(double db = 4){ cout << db;} // definition
int main(){
foo(); // usage
return 1;
}
But if I separate deklaration (-> *.h), definition (-> *.cpp) and usage (-> main) compiling suddenly returns an erro telling, there is no function foo(void), as it does not recognize that there is a default parameter. Any suggestions for that?
[/EDIT]
I wrote a c++-program running somehow like:
#include <iostream>
/* other includes */
using namespace std;
class my_class
{
private:
/* variables */
public:
/* function deklarations (just some short ones are only defined not declared) */
};
ostream& operator<<(ostream &out, my_class member);
/* Definition of the member functions and of the not-member-function */
int main()
{
/*some trial codes of member-functions */
return 1;
}
In one total file all compiled well in Eclipse and worked. Now I also wanted to try seperate in a main,class-header and class-cpp file (called them "my_class.h" and my_class.cpp").
For that i put in class-header:
#ifndef MY_CLASS_H_
#define MY_CLASS_H_
#include <iostream>
/* other includes */
using namespace std;
class my_class
{
/* ... */
};
ostream & operator<<(ostream &out, my_class member);
#endif /* MY_CLASS_H_ */
I put in class-cpp:
/* Definition of the member functions and of the not-member-function */
I put in main:
#include <iostream>
#include "my_class.h"
#include "my_class.cpp"
int main()
{
/*some trial codes of member-functions */
return 1;
}
This version is compiling with the g++ command in commandline:
g++ -o main.exe main.cpp
But it does not Compile in Eclipse. There it gives me the Error:
...\my_class.cpp:11.1: error: 'my_class' does not name a type
and same for all other member functions and variables. I tried to follow the instructions from here (I put just "my_class.h" in main and my_class.cpp, but then it did not compile in Eclipse and in command line (of course then with the my_class.cpp included). Eclipse gives me an Error, that makes me believe Eclipse does not see the "my_class.cpp":
...\main.cpp:288:47: error: no matching function for call to 'my_class::foo(...)'
where foo stands for the first member-function declard in the "my_class.cpp" file. First It gave the error for the constructor too, but as I put it's definition directly into the *.h file it worked well. (That's why I think, it does not see the "my_class.cpp" file)
I think I might be missing something very trivial as I am very new to Eclipse, but I don't see it. I tried to make my questions and information as short as possible.
default-parameters need to be declared in the header-file as it contains the declarations and not in the cpp file, which contains the definitions. (An additional mistake was to declare them in the definition). Found some help here. But why did it work, as I implemented it in one whole file?
Answer:
If default-parameter is in the cpp-file, the main file does not see it as
it looks only into the header-file
But if the whole code is included in just one file, the default-value
can be found in the definition too.
To explain myself:
I considered answering my question, because it gives a better overview of the whole question and the question will now not appear as unanswered. After reading this, I think that it is the right way to do so.
I am trying to relearn C++ after taking an intro course a few years ago and I’m having some basic problems. My current problem occurs when trying to use a friend function. Here is my code in 2 files.
First:
// fun.cpp
#include <iostream>
using namespace std;
class classA {
friend void funct();
public:
classA(int a=1,int b=2):propa(a),propb(b){cout<<"constructor\n";}
private:
int propa;
int propb;
void outfun(){
cout<<"propa="<<propa<<endl<<"propb="<<propb<<endl;
}
};
void funct(){ // ERROR HERE
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
Second:
// mainfile.cpp
#include <iostream>
#include "fun.cpp"
using namespace std;
int main(int nargin,char* varargin[]) {
cout<<"call funct"<<endl;
funct();
cout<<"exit main"<<endl;
return 0;
}
The error I am getting is "multiple definition of `funct()'". Am I using the wrong syntax when declaring it as a friend function?
Here is a highly simplified but hopefully relevant view of what happens when you build your code in C++.
C++ splits the load of generating machine executable code in following different phases -
Preprocessing - This is where any macros - #defines etc you might be using get expanded.
Compiling - Each cpp file along with all the #included files in that file directly or indirectly (together called a compilation unit) is converted into machine readable object code.
This is where C++ also checks that all functions defined (i.e. containing a body in { } e.g.
void Foo( int x){ return Boo(x); }) are referring to other functions in a valid manner.
The way it does that is by insisting that you provide at least a declaration of these other functions (e.g. void Boo(int); ) before you call it so it can check that you are calling it properly among other things. This can be done either directly in the cpp file where it is called or usually in an included header file.
Note that only the machine code that corresponds to functions defined in this cpp and included files gets built as the object (binary) version of this compilation unit (e.g. Foo) and not the ones that are merely declared (e.g. Boo).
Linking - This is the stage where C++ goes hunting for stuff declared and called in each compilation unit and links it to the places where it is getting called. Now if there was no definition found of this function the linker gives up and errors out. Similarly if it finds multiple definitions of the same function signature (essentially the name and parameter types it takes) it also errors out as it considers it ambiguous and doesn't want to pick one arbitrarily.
The latter is what is happening in your case. By doing a #include of the fun.cpp file, both fun.cpp and mainfile.cpp have a definition of funct() and the linker doesn't know which one to use in your program and is complaining about it.
The fix as Vaughn mentioned above is to not include the cpp file with the definition of funct() in mainfile.cpp and instead move the declaration of funct() in a separate header file and include that in mainline.cpp. This way the compiler will get the declaration of funct() to work with and the linker would get just one definition of funct() from fun.cpp and will use it with confidence.
The problem is that if you include fun.cpp in two places in your program, you will end up defining it twice, which isn't valid.
You don't want to include cpp files. You want to include header files.
The header file should just have the class definition. The corresponding cpp file, which you will compile separately, will have the function definition.
fun.hpp:
#include <iostream>
class classA {
friend void funct();
public:
classA(int a=1,int b=2):propa(a),propb(b){std::cout<<"constructor\n";}
private:
int propa;
int propb;
void outfun(){
std::cout<<"propa="<<propa<<endl<<"propb="<<propb<< std::endl;
}
};
fun.cpp:
#include "fun.hpp"
using namespace std;
void funct(){
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
mainfile.cpp:
#include <iostream>
#include "fun.hpp"
using namespace std;
int main(int nargin,char* varargin[]) {
cout<<"call funct"<<endl;
funct();
cout<<"exit main"<<endl;
return 0;
}
Note that it is generally recommended to avoid using namespace std in header files.
This problem happens because you are calling fun.cpp instead of fun.hpp. So c++ compiler finds func.cpp definition twice and throws this error.
Change line 3 of your main.cpp file, from #include "fun.cpp" to #include "fun.hpp" .
You have #include "fun.cpp" in mainfile.cpp so compiling with:
g++ -o hw1 mainfile.cpp
will work, however if you compile by linking these together like
g++ -g -std=c++11 -Wall -pedantic -c -o fun.o fun.cpp
g++ -g -std=c++11 -Wall -pedantic -c -o mainfile.o mainfile.cpp
As they mention above, adding #include "fun.hpp" will need to be done or it won't work. However, your case with the funct() function is slightly different than my problem.
I had this issue when doing a HW assignment and the autograder compiled by the lower bash recipe, yet locally it worked using the upper bash.
When I compile the program I am working on I get:
expected initializer before 'class'
error in my Class.h file. I looked up the error message on the internet, but couldn't find the exact error, although similar errors seem to be caused by missing semicolons but I don't see why I need one. This is the code the error points to, I have no other functions or classes before it.
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
In the Class.cpp file the double dAccountChange(double dChange) function is defined. I don't think this is where the error is coming from but this is the code;
double Account::dAccountChange(double dChange)
{
dAccountBalance += dChange;
return 0.0;
}
When I change the code in Class.h to look like this,
;
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
it doesn't generate an error message, but I can't work out why I need the semicolon before it as the only code I have before it are the following pre-processor lines.
#ifndef CLASS_H_INCLUDED
#define CLASS_H_INCLUDED
Any ideas on why the error is generated?
Most likely, in the header file you include immediately before class.h, you'll have something like:
class xyzzy {
int plugh;
}
without the closing semi-colon. That will make your code sequence:
class xyzzy {
int plugh;
}
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
which is clearly invalid. Inserting a semi-colon in class.h before the first line will fix it, but it's clearly the wrong place to put it (since it means every header file you include immediately after that one would need a starting semicolon - also, it's part of the definition in the first header and should be there).
Now that may not be the exact code sequence but it will be something very similar, and the underlying reason will be a missing piece of text in the previous header.
You should go back and put it in the earlier include file.
For example, consider:
include1.h:
class xyzzy {
int plugh;
}
include2.h:
class twisty {
int little_passages;
};
main.cpp:
#include "include1.h"
#include "include2.h"
int main (void) {
return 0;
}
Compiling this produces:
include2.h:3: error: multiple types in one declaration
but placing the semicolon at the end of include1.h (or start of include2.h though we've already established that's not a good idea) will fix it.
The problem is in one of the other headers, one that you #include ahead of class.h.
If you show us the top of your main cpp file, it might give a clue.