Classes in separate files in C++? - c++

I have copied this out of a book. I'm just not sure what to add in the main.cpp source file to make it run though.
I know that class declarations go in the .h file and implementations go in the .cpp file. What would I need to write in main.cpp?
I've tried lots of different things but I'm just getting so many error messages.
// cat.h
#ifndef ____2_cat_implementation__Cat__
#define ____2_cat_implementation__Cat__
#include <iostream>
using namespace std;
class Cat
{
public:
Cat (int initialAge);
~Cat();
int GetAge() { return itsAge;}
void SetAge (int age) { itsAge = age;}
void Meow() { cout << "Meow.\n";}
private: int itsAge;
};
#endif /* defined(____2_cat_implementation__Cat__) */
...
// cat.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
Cat::Cat(int initialAge)
{
itsAge = initialAge;
}
Cat::~Cat()
{
}
int main()
{
Cat Frisky(5);
Frisky.Meow();
cout << "Frisky is a cat who is ";
cout << Frisky.GetAge() << " years old.\n";
Frisky.Meow();
Frisky.SetAge(7);
cout << "Now Frisky is " ;
cout << Frisky.GetAge() << " years old.\n";
return 0;
}

Look at this part again:
Cat::Cat(int initialAge);
{
itsAge = initialAge;
Cat::~Cat()
You're missing the closing } for the constructor, as well as an extra ; after the function header.
On an unrelated note, don't use global names starting with underscore (like ____2_cat_implementation__Cat__), those names a reserved by the specification.

You have a missing } and unneccessary ;
//----------------------v
Cat::Cat(int initialAge);
{
itsAge = initialAge;
}
//^
What would I need to write in main.cpp
Usially, as you have pointed out, the .h file contains the declarations and the .cpp file - the definitions. Then, the main.cpp file should contain the main function (it's not necessary to name the file, containing the main function main.cpp. It could be anything.
So, in your example, you can create a main.cpp file with the following content:
// include the declarations file
#include "cat.h"
// include the header for cin/cout/etc
#include <iostream>
using namespace std;
int main()
{
Cat Frisky(5);
Frisky.Meow();
cout << "Frisky is a cat who is ";
cout << Frisky.GetAge() << " years old.\n";
Frisky.Meow();
Frisky.SetAge(7);
cout << "Now Frisky is " ;
cout << Frisky.GetAge() << " years old.\n";
return 0;
}
Other notes:
using namespace std; is bad practice, especially in header files. Use std:: instead (for example, std::cout, std::cin, std::string, etc)
as you have .h and .cpp files, don't put half of the implementation in the header and the rest - in the source file. Put all definitions inside the source files (unless you want to inline the functions, implemented in the header)
avoid using names, starting with __ or _ - they are reserved by the standard.

Related

program in C++ in OOP structure, splitting it at least into 3 files

I am doing my c ++ homework and am having difficulty in one little thing
Here is the text:
Create program in C++ in OOP structure, splitting it at least into 3 files. The class header should be put in header file (program.h). All the methods should be implemented outside the header – in a special C++ file (program.cpp). Function main should be put in yet another C++ file (main.cpp). By default, all class fields are private, but class methods - public. Unlike previous programs, it is not required to follow specific interface rules.
Create class "Date" with three numbers stored - year, month, day. The following class methods should be created: (1) a constructor to initialize an object with given initial values, (2) destructor which should notify about deleting the object, (3) method "change" with 3 parameters, (4) method "day" – which calculates and prints the weekday of date, (5) method "print", which prints the date.
I created 3 files main.cpp program.h programm.cpp
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "program.h"
using namespace std;
int main() {
Date s= Date(2002, 02, 18);
s.print();
s.change(1996, 02, 18);
s.print();
s.day();
return 0;
}
program.h
#ifndef ADD_H
#define ADD_H
#include <iostream>
#include <string>
struct Date {
public:
Date() {
year = 0;
month = 0;
dayc = 0;
}
//counstructor
Date(int n_year, int n_month, int n_day) {
year = n_year;
month = n_month;
dayc = n_day;
}
//destructor
~Date() {
std::cout << "Destructor deleted Date " << year << " " << month << " " << dayc << " " << std::endl;
}
void change(int c_year, int c_month, int c_day) {
year = c_year;
month = c_month;
dayc = c_day;
}
void day() {
//LONG CODE WITH CALCULATION
}
void print() {
std::cout << "Date is " << dayc << " " << month << " " << year << " " << std::endl;
}
private:
int year;
int month;
int dayc;
};
#endif
and empty programm.cpp
I need to do the OOP part and separate code to 3 files
The homework assignment tells you to separate code from the header. To do this you need to leave only declarations in the header like so:
Program.h:
#include <iostream>
class Date {
public:
Date(int, int, int);
void day();
private:
int _year;
int _month;
int _day;
};
Program.cpp:
#include "Program.h"
Date::Date(int year, int month, int day):
_year(year),
_month(month),
_day(day)
{
// only code should go here, not initializations
std::cout << "Constructor called" << std::endl;
}
void Date::day()
{
// your calculation
}
Your question suggests you haven't used more translation units yet, so you have to compile the Program.cpp first without linking (check your compiler manual), probably something like
c++ -o program.o -c program.cpp
and then compile + link the executable
c++ main.cpp program.o && ./a.out

Best Way to Deal With Headers and Source Files

I always arranged my C++ headers and source files this way:
prog.h
#include <iostream>
class Prog
{
public:
Prog(std::string);
~Prog();
void printName();
private:
std::string name;
};
#include "prog.cpp"
prog.cpp
Prog::Prog(std::string n):
name(n)
{
std::cout << "Program \"" << name << "\" started.\n";
}
Prog::~Prog()
{
std::cout << "Program \"" << name << "\" ended.\n";
}
void Prog::printName()
{
std::cout << "Program name is: \"" << name << "\".\n";
}
main.cpp
#include "prog.h"
int main()
{
Prog prog {"MyCalculator"};
prog.printName();
return 0;
}
But I recently discovered that it's common to arrange them this other way:
prog.h
class Prog
{
public:
Prog(std::string);
~Prog();
void printName();
private:
std::string name;
};
prog.cpp
#include <iostream>
#include "prog.h"
Prog::Prog(std::string n):
name(n)
{
std::cout << "Program \"" << name << "\" started.\n";
}
Prog::~Prog()
{
std::cout << "Program \"" << name << "\" ended.\n";
}
void Prog::printName()
{
std::cout << "Program name is: \"" << name << "\".\n";
}
main.cpp
#include <iostream>
#include "prog.h"
int main()
{
Prog prog {"MyCalculator"};
prog.printName();
return 0;
}
I find the first method more convenient, so is there any reason why I should prefer the second method over the first one?
Header files shouldn't include source code.
I think the first method could provoke dependency errors in a complex enough project (for example, using circular dependencies), because don't separate declaration and definition.
The compilation time is faster in the second one, because you can compile each source file separately.
Also, you might find this question useful.
The first version is what the book "Accelerated C++" (ed. 2000) suggests to do when first introducing header files for class declarations.
I suppose the second version can be seen as more elegant because it groups together all #include pre-compiler statements at the beginning of the program.

Way to handle the objects in C++

Every time when I run the code Compiler give the error of object already define and I don't know where I am making mistakes in the whole code.
Even if I do this all in one file it is working but I don't know why its not working in this style can anyone help me that where I am doing mistake in this code.
Any help would be appreciated.
Thank you
student.h
ifndef STUDENT
define STUDENT
class Student
{
public:
char student_no[10];
char student_name[20];
char student_address[20];
char student_score[20];
Student();
};
Student::Student()
{//constructor
student_no[0] = 0; student_name[0] = 0; student_address[0] = 0;
student_score[0] = 0;
}
#endif
student.cpp
using namespace std;
#include "writestr.cpp"
#include <fstream>
#include <string.h>
#include <iostream>
int main(){
char filename[20];
Student s;
cout << "Enter the file name:" << flush;
cin.getline(filename, 19);
ofstream stream(filename, ios::out);
if (stream.fail()) {
cout << "File open failed!" << endl;
return 0;
}
while (1) {
cin >> s; // read fields of person
if (strlen(s.student_name) == 0) break;
// write person to output stream
stream << s; // write fields of person
}
return 1;
}
Problems occured
This is the portion where I write the streaming code.
writestr.cpp
using namespace std;
#include "readper.cpp"
#include <fstream>
#include <string.h>
#include <iostream>
ostream & operator << (ostream & stream, Student & s)
{ // insert fields into file
stream << s.student_name << s.student_no << s.student_address
<< s.student_score;
return stream;
}
readper.cpp
using namespace std;
#include "student.h"
#include <fstream>
#include <string.h>
#include <iostream>
istream & operator >> (istream & stream, Student & s)
{ // read fields from input
cout << "Enter Student Name, or <cr> to end: " << flush;
stream.getline(s.student_name, 30);
if (strlen(s.student_name) == 0) return stream;
cout << "Enter Student Name: " << flush; stream.getline(s.student_name, 30);
cout << "Enter Student Id Number: " << flush; stream.getline(s.student_no, 30);
cout << "Enter Address: " << flush; stream.getline(s.student_address, 30);
cout << "Enter Score: " << flush; stream.getline(s.student_score, 15);
return stream;
}
You are defining (not just declaring) the constructor in the header file:
Student::Student()
{//constructor
student_no[0] = 0; student_name[0] = 0; student_address[0] = 0;
student_score[0] = 0;
}
This defines the constructor (generates the code) again and again in every cpp that includes the header file. Since this definition has no inline keyword, it may exist exactly once in the program, not multiple times. Defining the non-inline constructor in multiple translation units (cpp files) causes the error.
Possible solutions:
Move the constructor definition into the class, or
Prefix it by an inline keyword, or
Move it to one of the cpp files
Another issue: you include cpp files, which cause a lot more issues by declaring the same thing again and again. Simply add them to the project/makefile/etc, instead of including:
#include "writestr.cpp"

C++ Classes: errors with identifiers

I've a project in C++ with 2 classes.
MAIN.CPP:
#include <iostream>
#include <conio.h>
#include "Player.h"
#include "Enemy.h"
using namespace std;
int main()
{
const int startHealth = 100, startArmor = 50, startEnemyHealth = 70, startWeapon = 1;
Player *Mick = new Player(startHealth, startArmor, startWeapon);
Enemy *Mon = new Enemy(startEnemyHealth);
cout << "START!" << endl;
cout << Mick->Health << " : " << Mick->Armor << endl;
cout << "ENEMY ATTACKS!" << endl;
Mon->Attack(Mick);
cout << "DAMAGE TAKEN!" << endl;
cout << Mick->Health << " : " << Mick->Armor << endl;
cout << "YOU ATTACK!" << endl;
Mick->Attack(Mon);
cout << "ENEMY'S HEALTH!" << endl;
cout << Mon->Health << endl;
_getch();
return 0;
}
PLAYER.H
#pragma once
#include "Enemy.h"
class Player
{
public:
int Health, Armor;
int Weapon;
public:
Player(const int _startHealth, const int _startArmor, const int _startWeapon);
~Player();
void Attack(Enemy *_attackedEnemy);
};
ENEMY.H
#pragma once
#include "Player.h"
class Enemy
{
public:
float Speed;
int Damage;
int Health;
public:
Enemy(const int _startEnemyHealth);
~Enemy();
void Attack(Player *_attackedPlayer);
void Refresh(Enemy *_enemyToRefresh);
};
The errors that I get are these ones:
Meanwhile, these are the errors that CodeBlocks gives me:
Can someone help me with this issue?
The problem is that your Player class refers to your Enemy class, which also refers to your Player class:
class Enemy
{
void Attack(Player *_attackedPlayer);
}
class Player
{
void Attack(Enemy *_attackedEnemy);
}
What you need is forward declaration, to inform the compiler that a particular class exists, without telling it any information about this class.
Here you can add the following line in the file Enemy.h, before the definition of the Enemy class:
class Player;
Look at this question to see what you can or cannot do with forward declarations.
Why you need it here, even with the relevant #include directives
An #include directive is basically an instruction for the preprocessor that tells it to replace the directive by the included file. The #pragma once directive ensures that the file won't be included more than once for each translation unit.
In Main.cpp, here's what is going on:
#include "Player.h": the file Player.h is included.
The first line of Player.h is #include "Enemy.h": the file Enemy.h is included.
The first line of Enemy.h is #include "Player.h": since the file Player.h has already been included, the directive is ignored.
Definition of Enemy
Definition of Player
Definition of the main function
As you can see, even with the includes, at the time of the definition of the class Enemy, the compiler doesn't know that a class Player exists yet. This is the reason why you absolutely need a forward declaration here.

Using a header file, initialization file, and main file for structs in C++

I am having difficulty executing a program that I wrote with structs. My program has a header file, an initialization file, and a main file. When I compiled it, the compiler complained and later I found out that I forward declared my struct name as Company but initialized it using company so I changed it to Company but still the compiler complains after I did this. How can I fix this? Any help will be greatly appreciated. Below is my code for my three files:
structs.h:
#ifndef STRUCTS_H
#define STRUCTS_H
struct Company{
double salary;
int workers;
int bosses;
}
#endif
initialization.cpp:
Company a = {1200340.99, 30000, 3};
Company b = {500320.85, 5000, 2};
main.cpp:
#include <iostream>
#include "structs.h"
void PrintInfo(Company company){
using namespace std;
cout << "salary: " << Company.salary << endl;
cout << "workers: " << Company.workers << endl;
cout << "bosses: " << Company.bosses << endl;
}
int main(){
PrintInfo(a);
PrintInfo(b);
return 0;
}
You need a ; after the definition of struct Company
In PrintInfo you need to reference the object company (lowercase c) and not the class Company (uppercase C), e.g.
cout << "salary: " << company.salary << endl; // lowercase c
cout << "workers: " << company.workers << endl; // lowercase c
cout << "bosses: " << company.bosses << endl; // lowercase c
As a and b is initialized (globally) in a different source file you must redeclare them with external linkage in the source file that need to access them using the extern keyword, e.g.
// main.cpp
#include <iostream>
#include "structs.h"
extern Company a;
extern Company b;
/* ... */
Consider initializing a and b where they are used instead:
int main() {
Company a = {1200340.99, 30000, 3}; // Init here.
Company b = {500320.85, 5000, 2}; // Init here.
PrintInfo(a);
PrintInfo(b);
// return 0; // Unnecessary in main function.
}
In function PrintInfo, as you are not modifying the argument you should pass the class Company as reference to const to avoid copying, i.e. declare the function using this:
void PrintInfo(const Company& company)
A structure requires a ';' at the end
struct Company{
double salary;
int workers;
int bosses;
};
In addition to the other answers, the code in main.cpp knows nothing about a and b in your initialization.cpp.
You need to either add an extern declaration in structs.h or move those into main.cpp.
But, you should also consider not making them global variables, like this:
int main()
{
Company a = {1200340.99, 30000, 3};
Company b = {500320.85, 5000, 2};
PrintInfo(a);
PrintInfo(b);
return 0;
}