I've been programming in C# for a few years now, as it was my first language. I'm trying to brush up on my c++ because I will be working on something soon that is coded in that.
What is wrong with this code: (I know there might be a lot of things wrong. C++ is so different than C# in what it needs). Someone told me that I don't know how to declare classes correctly in C++, and that I need to define my classes using headers. Do I NEED headers? This is a small program just to test and would like to know if this can be accomplished without it. And are the missing headers the only issue here? I had a error about not being able to access Parse in Company, but when I add public in front of Company class name, it throws more errors.
AUGH! So frustrating.
#include "std_lib_facilities.h"
using namespace std;
class Employee
{
public:
string screen_name;
string real_name;
string current_job;
int employee_number;
Employee(int no, string name1, string name2, string current_jobin)
{
screen_name=name1;
real_name=name2;
employee_number=no;
current_job=current_jobin;
}
};
class Project
{
public:
Vector<Employee> Employees;
int max_worker_quota;
int project_id;
string project_name;
Project(int no_in,int max_in,string title_in)
{
max_worker_quota=max_in;
project_name=title_in;
project_id=no_in;
}
};
unsigned int split(const std::string &txt, vector<std::string> &strs, char ch)
{
unsigned int pos = txt.find( ch );
unsigned int initialPos = 0;
strs.clear();
// Decompose statement
while( pos != std::string::npos ) {
strs.push_back( txt.substr( initialPos, pos - initialPos + 1 ) );
initialPos = pos + 1;
pos = txt.find( ch, initialPos );
}
// Add the last one
strs.push_back( txt.substr( initialPos, std::min( pos, txt.size() ) - initialPos + 1));
return strs.size();
}
class Company
{
Vector<Employee> Employeelist;
Vector<Project> Projectlist;
void Parse(string input)
{
//Case Statements
vector<string> temp;
split( input, temp, ' ' );
if (temp[0]=="S")
{
//Add Employee to Company
Employee myEmployee=Employee(atoi(temp[1].c_str()),temp[2],temp[3],temp[4]);
Employeelist.push_back(myEmployee);
}
else if (temp[0]=="C")
{
//Add Project to Company
Project myProject=Project(atoi(temp[1].c_str()),atoi(temp[2].c_str()),temp[3]);
Projectlist.push_back(myProject);
}
else if (temp[0]=="L")
{
//Add Employee to Project list
//Not Implemented-Find Project by temp[1] which is a int
}
else if (temp[0]=="A")
{
}
else if (temp[0]=="D")
{
}
else if (temp[0]=="PS")
{
}
else if (temp[0]=="PC")
{
}
}
};
int main(int argc, char *argv[])
{
string input;
cout<<"Command:: ";
cin>>input;
Company myCompany;
myCompany.Parse(input); //Input is in the format X Name Name etc etc. Arguments separated by spaces
return 0;
}
First of all, you don't need headers for test purposes. But you can not make a real program without them, because the headers define the interface of separately compiled program parts. That's the way the C/C++ work, no way around.
Second, you have to add public:
to your Company
class and deal with the following errors. It is just like the C# stuff: you have to make a function defined public void Parse(string)
to be able to access it from outside the class. The C++ way is
class Foo {
public:
void Bar();
};
Third, it is unconventional in C++ to define non-trivial functions inside class definition (the only exception being template classes). That's the other side of the headers story tho.
OK, here is a brief explanation of basic header-related stuff.
Program is usually divided into the set of separately compiled files, that is to say translation units. Each unit usually consist of one .cpp
file and one or more header files (.h
). When these files are compiled you are getting a single binary .obj file. This file contains objects - the code for your functions and stuff needed to initialize global (and namespace) objects. To make a program you need to pass one or more object files to linker. In VS it happens behind the scene. You just add a .cpp file to your project tree and IDE will configure the project dependencies accordingly.
This is how your code may look like:
//File: employee.h
#ifndef EMPLOYEE_HDR /* include guard */
#define EMPLOYEE_HDR
#include <string>
using std::string;
class Employee {
public:
Employee (int no, string name1, string name2, string current_jobin);
void PayBonus(int amount);
void Fire(string reason);
int GetSalary() const
{ return m_Salary; }
/*...*/
protected:
int m_Salary;
string m_FirstName;
/* ... */
};
#endif
//File: employee.cpp
#include "employee.h"
Employee::Employee (int no, string name1, string name2, string current_jobin)
{
//definition
}
void Employee::PayBonus(int amount)
{
//definition
}
void Employee::Fire(string reason)
{
//definition
}
/* define other non-trivial class functions here */
//File: company.h
#ifndef COMPANY_HDR /* include guard */
#define COMPANY_HDR
#include <vector>
using std::vector;
#include "employee.h"
class Company {
public:
Company();
void Hire(string name);
void WorldCreditCrunch() //life is unfair
{ FireEveryone(); }
void Xmas(); //pays $5 bonus to everyone
/* ... */
protected:
vector<Employee> m_Staff;
void FireEveryone();
/* ... */
};
#endif
//File: company.cpp
#include "company.h"
Company::Company()
{
//definition
}
void Company::Hire(string name)
{
//calculate new employee ID etc
m_Staff.push_back(Employe( /*...*/));
}
void Company::FireEveryone()
{
for(size_t i = 0; i < m_Staff.size(); ++i)
m_Staff[i].Fire();
}
void Company::Xmas()
{
for(size_t i = 0; i < m_Staff.size(); ++i)
m_Staff[i].PayBonus(5);
}
/* ... */
//File: main.cpp
#include "company.h"
int main()
{
Company c;
c.Hire("John Smith");
/* ...*/
return 0;
}
So, basically we gonna have employee, company and main units. The definition of Employee class in employee.h
contains non-trivial functions declaration. A simple function like GetSalary()
is defined right inside the class. It gives a hint to the compiler to inline it. The employee.cpp
contains the rest of function definitions;
The company.h
file has #include "employee.h"
preprocessor statement. So we may use Employee objects in the class definition and in its implementation file (company.cpp
).
The main.cpp
contains the program entry point. It is able to use Company class cause it includes "company.h".
If we change something in the Employee::Hire() function implementation, only employee.obj
will be recompiled. This is the main purpose of such program organization. But if we change the Employee interface (class definition in employee.h
) every program unit will require recompilation.
Include guards are needed in case you do something like this:
#include "employee.h"
#include "company.h" /* will contain the 2nd inclusion of employee.h which will be
prevented by include guard */
Projects based on Microsoft Visual C++ often use #pragma once
for the same purpose. It is easier to use but generally not portable.
If you put, for example, Employee::Hire definition in the employee.h
the compiler will put the function code in both employee.obj and company.obj (cause the company.h
includes employee.h
). When you try to link in such situation the linker will encounter 2 versions of the same function code and will give an error. Inline functions are not compiled in into separate entities and thus don't cause such error. Same goes about template code which is generated only when the template is instantiated. So, several translation units may have code for the same non-inline template functions.
It is up to programmer to define the parts boundaries of the program. You may put Company and Employee into single translation unit, if you want. The VS wizards tend to make a .h/.cpp pair for each major class tho. Try to make an MFC project and see for yourself.
These are the basics. As I mentioned in the comment above, you can get a full picture of such stuff from Stroustrup's "The C++ programming language"