Linking c++ files using CMakeLists.txt - c++

Okay, so I just started dabbing into c++ and I'm hoping to get ahead on my classes in the fall but instead of using the a compiler I've been using nitrous.io as an IDE. Anyways long story short, I'm using CMakeLists.txt to compile and run but I've been running into a lot of difficulties when trying to link together an interface, it's corresponding cpp file and a main function.
Gradebook.h
//Gradebook.h
#include <string>
using namespace std;
class Gradebook
{
public:
Gradebook(string n);
Gradebook();
void setCourse(string n);
string getCourse();
void displayMessage();
private:
string course;
};
Gradebook.cpp
//Gradebook.cpp
#include "Gradebook.h"
#include <iostream>
using namespace std;
Gradebook::Gradebook(string n)
{
course = n;
}
Gradebook::Gradebook()
{
cout << "Default constructor used." << endl;
}
void Gradebook::setCourse(string n)
{
course = n;
}
string Gradebook::getCourse()
{
return course;
}
void Gradebook::displayMessage()
{
cout << "Welcome to " << course << "'s gradebook." << endl;
}
GradebookRunner.cpp - main function
#include "Gradebook.h"
int main()
{
Gradebook g("Intro to c++");
g.displayMessage();
return 0;
}
CMakeLists.txt - I'm 95% sure that the syntax and linking is done correctly in the .h and .cpp files, this is where I believe I'm making the mistake.
##I've tried to use different combinations of Gradebook and Gradebook.cpp in here.
cmake_minimum_required(VERSION 2.6)
project(Gradebook)
add_executable(Gradebook Gradebook.cpp)
Any help will be much appreciated :D

Simply add all files that belong to the executable (both headers and source files, so you have them all in IDE and dependencies are correctly resolved by CMake).
add_executable(Gradebook Gradebook.cpp GradebookRunner.cpp Gradebook.h)
Note that GLOB feature could be tricky.

Related

Several strange errors when building project using separate files C++

I'm able to build and run a particular project in Visual Studio when all of the code is in one main .cpp file, but when I separate the file into a class (.cpp and .h) and main .cpp file, I get several weird errors.
Here is the code when it's in 3 separate files, and not working:
//main.cpp
#include "student.h"
#include <string>
#include <iostream>
using namespace std;
int main()
{
std::cout << "Hello World!\n";
Student student;
student.setStudentID("A1C");
student.print();
}
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
class Student
{
public:
Student();
string getStudentID() const;
void setStudentID(string studentID);
void print();
private:
string studentID;
};
#endif
//Student.cpp
#include "Student.h"
#include <string>
#include <iostream>
using namespace std;
Student::Student() {
this->studentID = "default";
}
string Student::getStudentID() const {
return this->studentID;
}
void Student::setStudentID(string studentID) {
this->studentID = studentID;
}
void Student::print() {
cout << "student ID: " << studentID << endl;
}
Here is the code when it's all in one main.cpp file, and working:
#include <string>
#include <iostream>
using namespace std;
class Student
{
public:
Student();
string getStudentID(); //const?
void setStudentID(string studentID);
void print();
private:
string studentID;
};
int main()
{
std::cout << "Hello World!\n";
Student student;
student.setStudentID("A1C");
student.print();
}
Student::Student() {
this->studentID = "default";
}
string Student::getStudentID() { //const?
return this->studentID;
}
void Student::setStudentID(string studentID) {
this->studentID = studentID;
}
void Student::print() {
cout << "student ID: " << studentID << endl;
}
Here are some of the errors that I get:
In the file Student.h you are using string, but string is not (yet) known. Read the Include file from top to bottom. Nowhere in the file is there any hint as to what string is supposed to be.
#include <string> in your Student.h file will introduce std::string to the file. From here on, std::string will be valid. But that's still not enough, since you are using string and not std::string in your class.
Do not include a using namespace std in your header file. If you do so, you force this namespace on all your "customers" of the header file. If any other file includes your Student.h with the using namespace in it, they will also get the using namespace... statement, even if they do not want it. Headerfiles should be self contained and should not introduce stuff, others may not want.
Also do not add a using std::string in your header file. While not as bad as a using namespace std there may be (and later in your professional life will be) instances, where you have different kinds of string. Perhaps a std::string and an oldfashioned::string or utf_something::string.
For simplicity, just write std::string studentId. IOW, use the fully qualified name of string in your header file.
In .cpp files these rules are somewhat relaxed, since no other file will include your .cpp file.
Bonus:
lookup #pragma once
always include system headers before your own headers
But beware of include order. Every header file should include all headers it needs, because ...
... the worst thing that can happen is that your code changes depending on the order in which you include headers. It should not matter. Including "Student.h" should introduce the Student class and nothing else.
Bonus++
take your time to learn about the C(++) preprocessor. #include is not really a C++ language statement like class, for etc... It is just a directive for the compiler to read the included file first.
Your compiler will have a switch (such as /P with Microsoft Visual C++) which will not compile the code but produce the actual included files and store the in a *.p (or something) file. It will let you see what the preprocessor does with your code before it is passed on to the compiler. It's an interesting and teaching experience. Try it. Don't be put off by the seemingly complex file. Search for "class Student" in that file and take it from there.
change student.h to this
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
class Student
{
public:
Student();
std::string getStudentID() const;
void setStudentID(std::string studentID);
void print();
private:
std::string studentID;
};
#endif
and it compiles and runs fine
BTW.
dont do this
void Student::setStudentID(string studentID) {
this->studentID = studentID;
}
have a naming convention for fields in a class so they are distinct
ie
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
class Student
{
public:
Student();
std::string getStudentID() const;
void setStudentID(std::string studentID);
void print();
private:
std::string studentID_; <<<<========
};
then
void Student::setStudentID(string studentID) {
studentID_ = studentID;
}
why, because
First its the accepted way in c++ world (the naming standard might differ, m_ prefix is common too)
second you might write this
void Student::setStudentID(string studentID) {
studentID = studentID;
}
which will compile but is maybe not what you mean. Of course here its obvious but in denser code, not so much

C++ warning: pragma once in main file

I'm have an issue with compiling my program with g++ 8.3. I have approx 10 classes in a program. These classes are placed in header files and their full definitions are in .cpp files. I'm including these classes the same way as in this code:
main.cpp:
#include "CPerson.h"
int main()
{
CPerson person1(10 , "Peter");
CPerson person2(20 , "James");
person1.Print();
person2.Print();
return 0;
}
CPerson.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CPerson{
protected:
int m_Age;
string m_Name;
public:
CPerson( const int age , const char * name ) :
m_Age(age), m_Name(name){}
void Print(){
cout << "Hello Im " << m_Name << " - " << m_Age << "years old" << endl;
}
};
When I try to compile this C++ program with the following command:
g++ main.cpp CPerson.h
I get this message:
warning: #pragma once in main file
Is here anything I can do about this, or is it just bug in the g++ compiler?
SOLVED:
You need to compile only .cpp files with declarations of methods of each class thats defined in Class.h
You get the warning because you are compiling a file that contains #pragma once. #pragma once is only intended to be used in headers, and there is no need to compile headers; hence the warning. Solution: Don't compile headers.

'cout' is not a member of 'std' (Progect File c++)

I created a new project in c++ but i keep getting the same error
Main.cpp
#include <iostream>
#include <string.h>
#include "Computer.cpp"
#include "Computer.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
Computer.h
#ifndef COMPUTER_H_INCLUDED
#define COMPUTER_H_INCLUDED
#include <string>
class Computer
{
public:
std::string marca;
float prezzo;
bool acceso;
Computer();
void Accenditi();
void Spegniti();
void ImpostaMarca(std::string m);
void ImpostaPrezzo(float p);
};
#endif
Computer.cpp
#include "Computer.h"
Computer::Computer()
{
}
void Computer::Accenditi()
{
if(!acceso)
{
acceso = true;
}
else
{
std::cout << "Sono già acceso";
}
}
void Computer::Spegniti()
{
if(acceso)
{
acceso = false;
}
else
{
std::cout << "Sono già spento";
}
}
void Computer::ImpostaMarca(std::string m)
{
marca = m;
}
void Computer::ImpostaPrezzo(float p)
{
prezzo = p;
}
The Problem
i don't understand what's wrong with Computer.cpp, i keep getting "cout is not a member of std". I tryed to add "using namespace std" and i also tryed to add the library #include but i get a new file called "makefile.win". How can i fix this error ?
You need to include iostream header in your Computer.cpp file as such:
include <iostream>
and to make your life easier, you can also add:
using std::cout;
using std::endl;
right at the bottom of your include, that way you don't have to keep adding "std::cout" everytime, you can just use "cout"
Also want to add:
You can remove the include computer.cpp from your main.cpp and just leave the header. The C++ linker will automatically link your computer.h and computer.cpp together since .cpp includes the header, and your main includes the computer.h
Add # include <iostream> at the files that you use std::cout and std::cin.

C++ Code::Blocks not compiling with header files

Good evening! (morning?)
I was wondering if anyone is familiar with the following issues. There are three files here, which are Cat.cpp, Cat.h, and CatMain.cpp. The issues are as follows:
When I try to build Cat.cpp, I get the error "undefined reference to WinMain#16".
When I try to build CatMain.cpp, I get undefined reference errors for the speak and jump functions.
The files are in the same folder and the code is just one-liners:
Cat.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
void speak()
{
cout << "meow" << endl;
}
void jump()
{
cout << "meow?" << endl;
}
Cat.h
#ifndef CAT_H
#define CAT_H
void speak();
void jump();
#endif // CAT_H
CatMain.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
int main()
{
speak();
jump();
return 0;
}
Is there anything wrong with this code? Or is anyone aware of whether or not this is a Code::Blocks or a compiler issue?
Any help is greatly appreciated =)
All that your code does as of now is something like this :
Cat.cpp ::
#include <iostream>
using namespace std;
void speak();
void jump();
void speak()
{
cout << "meow" << endl;
}
void jump()
{
cout << "meow?" << endl;
}
CatMain.cpp ::
#include <iostream>
using namespace std;
void speak();
void jump();
int main()
{
speak();
jump();
return 0;
}
You Cat.cpp has a main method missing because of which it wouldn't compile.
Your CatMain.cpp does not have any definition for speak() and jump(), hence undefined error.
Point : CatMain.cpp doesn't know what Cat.cpp is trying to work out.
int main() { return 0; }
added to Cat.cpp should let it compile.
void speak(){
cout << "defined" << endl;
}
void jump(){
cout << "defined" << endl;
}
added to CatMain.app should work for it as well.
Your code is fine.
Most probably you don't want to compile separate files but project as whole. You should add both cpp to project in your IDE and linker will link them together resolving both issues.

C2061: syntax error : identifier 'string' - Behaving weird

I am trying to learn C++, however, the parameter to a method I have in my own class is misbehaving. When it uses a dataType of 'int', it works fine with no errors, but when I attempt to change it to a 'string' dataType, the program crashes with this error.
Error 1 error C2061: syntax error : identifier 'string' in temp.h ln
8 col 1
The classes I am using are as follows:
WORKING CODE
TesterClass.cpp // Entry Point
#include "stdafx.h"
#include "Temp.h"
int _tmain(int argc, _TCHAR* argv[])
{
Temp tmp;
tmp.doSomething(7);
return 0;
}
Temp.h
#pragma once
class Temp
{
public:
Temp();
void doSomething(int blah);
};
Temp.cpp
#include "stdafx.h"
#include "Temp.h"
#include <iostream>
#include <string>
using std::string;
Temp::Temp()
{
std::cout << "Entry" << std::endl;
string hi;
std::cin >> hi;
std::cout << hi << std::endl;
}
void Temp::doSomething(int blah)
{
std::cout << blah;
}
BROKEN CODE
Temp.h
#pragma once
class Temp
{
public:
Temp();
void doSomething(string blah);
};
Temp.cpp
#include "stdafx.h"
#include "Temp.h"
#include <iostream>
#include <string>
using std::string;
Temp::Temp()
{
std::cout << "Entry" << std::endl;
string hi;
std::cin >> hi;
std::cout << hi << std::endl;
}
void Temp::doSomething(string blah)
{
std::cout << blah;
}
When I adjust the parameter 'blah' to be a string, in both the .h and .cpp file, the problem occurs.
I have looked around, but none of the answers seem to solve my problem. I would greatly love help on this an I am out of ideas. I have tried reinstalling C++, messing with:
using namepace std;
using std::string;
std::string instead of string
etc.
If you know how to solve my problem I would love to hear from you. I am more than happy to provide more information.
C++ performs single-pass compilation, so std::string needs to be declared before you use it at all - including in the header file.
// Temp.h
#pragma once
#include <string>
class Temp
{
public:
Temp();
void doSomething(std::string blah);
};
I would encourage you to be specific in your header files when specifying classes like this, because you might easily come across another library that defines it's own string and then you would run into naming conflicts. Save the using import statements for your cpp files.
πάντα ῥεῖ had the write answer, thankyou!
They said to use std::string when needed, and to also #include <string> in the header file.