Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Splitting classes in .h files and .cpp files. 3

Status
Not open for further replies.

KarlSciberras

Programmer
Dec 8, 2006
9
MT
Lately I have been experimenting with splitting classes in header files and cpp files. As far as I knew, the basic concept when splitting classes in header files and cpp files was the following:

header file --> declaration of class
cpp files --> implimentation / definition of class

However, the following did not

-------------------------------------
Code:
//STUDENT.H
class student
{
public:
	int id; 
	student::student(); 
};
-------------------------------------
Code:
//STUDENT.CPP

student::student() 
{
	student::id = 1; 
}
-------------------------------------
Code:
//MAIN.CPP
#include <iostream> 
#include <conio.h> 
#include "student.h"
using namespace std; 

void main()
{
	student bob; 
	cout <<bob.id; 
	getch();
}
-------------------------------------
When the above code was compiled, i got the following errors:

error C2653: 'student' : is not a class or namespace name
error C2653: 'student' : is not a class or namespace name
error C2065: 'id' : undeclared identifier

After trying out some major possibilities of work arounds, the following worked:

-------------------------------------
Code:
//STUDENT.H
class student
{
public:
	int id; 
	student::student(); 
};
--------------------------------------
Code:
//STUDENT.CPP
class student
{
public:
	int id; 
	student::student(); 
};

student::student() 
{
	student::id = 1; 
}
---------------------------------------
Code:
//MAIN.CPP
#include <iostream> 
#include <conio.h> 
#include "student.h"
using namespace std; 

void main()
{
	student bob; 
	cout <<bob.id; 
	getch();
}
-------------------------------------

The difference of the two examples of code described above is the following:

Example 1 - Student class declaration NOT included in student.cpp

Example 2 - Student class declaration was included in student.cpp

Would anyone please explain me, why a declaration of the student class is also required in the student.cpp so that the program compiles successfully? From what I learnt the header files should include the declaration and the cpp files should include the actual implementation...but apparently the decleration is also required in the cpp file,
is this true?
 
The main problem is that your implementation file needs to include the header file.

Like so
Code:
// s.h
#ifndef INCLUDED_S_H
#define INCLUDED_S_H

class student
{
  public:
    int id;
    student();
};

#endif
Code:
// s.cpp
#include "s.h"
student::student()
{
    id = 1;
}
Code:
#include <iostream>
#include "s.h"
using namespace std;

int main()
{
    student bob;
    cout <<bob.id;
    return 0;
}
Some points to note
1. main always returns int, never void
Your compiler might let you do it, but to be sure of portability, use int
2. class members don't need the class prefix when they're inside the class to begin with.
3. All header files should have include guards to protect from including the files several times (which would lead to multiple declarations).

To compile the program, compile all the .cpp files (or add them to your project)
[tt]
$ g++ foo.cpp s.cpp
$ ./a.exe
1[/tt]

--
 
Add #include "student.h" in the student.cpp - that's all (and remove class student {} declaration from this file). Now include student.h in all program units where you need this class. Compile class implementation with this class declaration header file.

Apropos, no need to qualify member names in class declaration body. Be simpler:
Code:
class student
{
public:
    student();
    int id;
    // etc...
};
Are you sure you want public id member?..
 
Think about it as if you were the compiler. In Example 1, you are faced with
Code:
student::student
In the early days of C++ before namespaces were invented, there was only one meaning: the member function student in the class student. Since namespaces started, there is a second definition: the function student in the namespace student. Having said that, the way you've done both examples isn't quite standard i.e. most people don't code like that. It isn't wrong. Normally, you'd see something like this
Code:
//STUDENT.H
class student
{
public:
    int id;
    student();  // No need to prefix with student
};
Code:
//STUDENT.CPP
#include "student.h"  // tells whether it is namespace or class
student::student()
{
    // no need to prefix with student unless you hit the
    // diamond problem or same declaration in multiple
    // inheritence class
    id = 1;
}
Code:
//MAIN.CPP
#include <iostream>
#include <conio.h>
#include "student.h"
using namespace std;

void main()
{
    student bob;
    cout << bob.id << endl;  // endl does a flush
    getch();
}
 
Thanks to all of you guys :)

I will be trying your suggestions out, this is some really valuable help, Cheers.
 
After reading all your suggestions, I came up with the following code. I created another class called studentCls which is basically an array of the student class created previously. It also includes some other functions to populate the array and display them. I split the code as shown below:

-student.h
student class declaration.
student.h also declares to have a friend named
studentCls.h, which will be accessing it's private
members in order to build a more complex class.

-student.cpp
student class implementation

-class.h
studentCls class declaration.
studentCls class #includes student.h so make use of
it's friend class.

-class.cpp
studentCls class implementation.

-main.cpp
Includes studentCls. Public member functions of the
studentCls are called for testing purposes

Code:
//STUDENT.H
#ifndef STUDENT_H	
#define STUDENT_H

class student
{
	friend class studentCls; 
	int studentID;
	char studentName[15];
	student(); 	
};

#endif
Code:
//STUDENT.CPP 
#include<string.h>
#include"student.h"

student::student() 
{
	student::studentID = 0;
	strcpy(student::studentName, ""); 
}
Code:
//CLASS.H
#ifndef CLASS_H
#define CLASS_H
#include "student.h"

class studentCls
{
	student someStudents[5];
public:
	void displayStudents();
	void SetStudents();
	studentCls();
};
#endif
Code:
//CLASS.CPP
#include <iostream>
using namespace std;
#include "class.h"

studentCls::studentCls()
{
	int i=0; 
	for (i=0; i<5; i++)
	{	
		someStudents[i].studentID = (i+1); 
		strcpy(someStudents[i].studentName, "");
	}
}

void studentCls::SetStudents()
{
	int i=0;
	char input[10]; 
	for (i=0; i<5; i++)
	{	
		cout<<"Please enter name of student ID "
			<<someStudents[i].studentID<<endl;
		cin>>input; 
		strcpy(someStudents[i].studentName, input); 
	} 
}

void studentCls::displayStudents()
{
	int i=0; 
	for (i=0; i<5; i++)
	{	
		cout<<"The name of Student ID "<<someStudents[i].studentID
			<<" is: "<<someStudents[i].studentName<<endl; 
	}
}
Code:
//MAIN.CPP
#include <iostream> 
#include <conio.h> 
using namespace std;
#include "class.h"

int main()
{
	studentCls amber;
	amber.SetStudents(); 
	amber.displayStudents(); 
	getch();
	return 0; 
}

THANKS TO ALL!!
 
I'm glad to see it.
In pursuit of:
1. Declare student as a struct instead of a class (make all members public, no need in friendship in that simple case;).
2. Use std::string instead of a very dangerous char[].
3. Use vector<student> instead of fixed size student[] array.
4. Wait for user with common system("pause") call instead of non-standard and unreliable getch() from <conio.h>

Good luck!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top