Here's a commented example which hopefully will show the difference between inheritance and composition.
#include <string>
#include <vector>
#include <iostream>
class Person
{
protected:
// a person always has a name and a positive age.
std::string name;
unsigned int age;
public:
// create the person by giving it a name and an age.
// A person without name and age mustn't exist.
Person( std::string _name, unsigned int _age )
{
// this is the simplified version to assign member variables...
// for a better version see class teacher
name = _name;
age = _age;
}
// return the name, but promise to leave the class and its members intact ("const")
std::string getName() const
{
return name;
}
// return the age, but promise to leave the class and its members intact ("const")
unsigned int getAge() const
{
return age;
}
};
class Student : public Person
{
protected:
// std::vector is an array of variable length.
// see
std::vector<int> votes;
public:
Student( std::string _name, unsigned int _age )
: Person( _name, _age ) // create the base class - we have to tell it the name and age
{
// nothing to do here
}
std::vector<int> getVotes() const
{
return votes;
}
// set the whole "votes" array. This changes the class (respectively the "votes" member) so no "const"
void setVotes( std::vector<int> _votes )
{
votes = _votes;
}
// this adds a single vote
void addVote( int _vote )
{
votes.push_back( _vote );
}
// this returns the current number of votes
int getNumVotes() const
{
return votes.size();
}
};
class Teacher : public Person
{
protected:
unsigned int salary;
public:
// a teacher is a person and thus has a name and an age, but also a salary
Teacher( std::string _name, unsigned int _age, unsigned int _salary )
: Person( _name, _age ) // create the base class - we have to tell it the name and age
, salary( _salary ) // here the member salary is set - better method than to do it in the block.
{
// nothing to do here
}
unsigned int getSalary() const
{
return salary;
}
void setSalary( unsigned int _salary )
{
salary = _salary;
}
};
// a school class is a standalone class, because it is no person, no teacher, no student.
// But it CONTAINS a teacher and some students.
class Schoolclass
{
private:
Teacher teacher;
std::vector<Student> students;
public:
Schoolclass( Teacher _teacher )
: teacher(_teacher)
{
}
// this adds a student
void addStudent( Student _student )
{
students.push_back( _student );
}
std::vector<Student> getAllStudents() const
{
return students;
}
Teacher getTeacher() const
{
return teacher;
}
// now let's return all persons in the school class - this includes both teacher and students
std::vector<Person> getAllPersons() const {
// create a vector of persons we can later on return.
std::vector<Person> result;
// add the teacher first.
// Although his class is "Teacher", we can add him to a vector or "Person"s, because he
// is also a person (Teacher inherits Person). This is one of the benefits of inheritance.
result.push_back(teacher);
// Then add all children.
// We can iterate them.
for( int i = 0; i<students.size(); i++ )
result.push_back( students[i] );
// return the vector of persons.
return result;
}
};
int main()
{
// create a teacher first, because the school class can not exist without teacher.
Teacher mrSmith( "Smith", 36, 2000 );
// Then create some students.
Student tim( "Tim", 12 );
Student laura( "Laura", 13 );
Student sam( "Sam", 12 );
// create the school class with the teacher
Schoolclass schoolclass( mrSmith );
// add the students.
schoolclass.addStudent(tim);
schoolclass.addStudent(laura);
schoolclass.addStudent(sam);
// now let's check it. Print the teacher first.
std::cout << "Teacher: " << schoolclass.getTeacher().getName();
std::cout << " Age: " << schoolclass.getTeacher().getAge();
std::cout << " Salary: " << schoolclass.getTeacher().getSalary() << std::endl << std::endl;
// Then print all the children.
std::vector<Student> students = schoolclass.getAllStudents();
for( int i = 0; i<students.size(); i++ )
{
std::cout << "Student: " << students[i].getName();
std::cout << " Age: " << students[i].getAge() << std::endl;
}
std::cout << std::endl;
float averageAge = 0;
// get all persons from the class.
std::vector<Person> allPersons = schoolclass.getAllPersons();
for( int i=0; i<allPersons.size(); i++ )
{
averageAge += allPersons[i].getAge();
}
averageAge = averageAge / allPersons.size();
std::cout << "There are " << allPersons.size() << " persons in the class (including the teacher)" << std::endl;
std::cout << "Their average age is " << averageAge;
char c;
std::cin >> c;
}
Note: At some places it's a bit simplified (e.g. as a trained c++ programmer you would of course hand over strings and vectors as const ref)