Example 3 - Review of classes, constructors and destructors

// File: day2ex3.cpp - Review example 3
#pragma warning(disable : 4996)	// Disable MS warning: 'strcpy': This function or variable may be unsafe ...

#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;

const unsigned short noAssignments = 8;

class Name
{
public:
	Name(const char* name);
	Name(const Name&);
	~Name();
	const char* get_name() const { return name_ ? name_ : ""; }
private:
	char* name_;
};

class Student
{
	static const unsigned short MaxTotalPoints;

	Name name_;
	unsigned int id_;
	unsigned short assGrade_[noAssignments];
	unsigned short labExTotal_;
	unsigned short midterm_;
	unsigned short final_;
	unsigned short minOfFirst7Ass() const;
public:
	Student(const char*, unsigned int,
		unsigned short, unsigned short, unsigned short, unsigned short,
		unsigned short, unsigned short, unsigned short, unsigned short,
		unsigned short, unsigned short, unsigned short);
    Name name() const { return name_; }
	unsigned short totalPoints() const;
	const char* grade() const;
};

class Class
{
public:
    Class();
    ~Class();
    void addStudent(Student*);
    static unsigned short getNoStudents();
    void printClassGrades() const;
private:
    Student** students;
    static unsigned short NoStudents;
    static const unsigned short MaxClassSize;
};

unsigned short Class::NoStudents = 0;
const unsigned short Class::MaxClassSize = 40;

Class::Class() : students(new Student*[MaxClassSize]) {}
Class::~Class()
{
    for (unsigned short i = 0; i < NoStudents; i++) {
        delete students[i];
    }
}

void Class::addStudent(Student* ptrStudent)
{
    students[NoStudents++] = ptrStudent;
}

unsigned short Class::getNoStudents()
{
    return NoStudents;
}

void Class::printClassGrades() const
{
    for (unsigned short i = 0; i < NoStudents; i++) {
        cout << students[i]->name().get_name() << ' ' << students[i]->totalPoints()
            << ' ' << students[i]->grade() << endl;
    }
}
int main()
{
    Class CIS29;
    CIS29.addStudent(new Student("Joe Bentley",12345678,20,17,9,19,17,12,10,16,50,47,72));
    CIS29.addStudent(new Student("John Doe",12345679,19,19,19,15,17,11,11,17,60,50,92));
    CIS29.addStudent(new Student("Mary Doe",12345680,20,20,20,19,20,10,20,19,55,40,91));

    cout << "CIS29 - number of students = " << Class::getNoStudents() << endl;
    CIS29.printClassGrades();
}


Name::Name(const char* name = 0)
: name_(name ? new char[strlen(name)+1] : 0)
{
	if (name) strcpy(name_,name);
}

Name::Name(const Name& other)
: name_(new char[strlen(other.name_)+1])
{
	strcpy(name_,other.name_);
}

Name::~Name()
{
	if (name_) {
		delete[] name_;
		name_ = 0;
	}
}

const unsigned short Student::MaxTotalPoints = 350;

Student::Student(const char* name, unsigned int id,
				 unsigned short a1, unsigned short a2, unsigned short a3, unsigned short a4,
				 unsigned short a5 , unsigned short a6, unsigned short a7, unsigned short a8,
				 unsigned short labextotal, unsigned short midterm, unsigned short final)
				 : name_(name), id_(id), labExTotal_(labextotal), midterm_(midterm),final_(final)
{
	assGrade_[0] = a1;
	assGrade_[1] = a2;
	assGrade_[2] = a3;
	assGrade_[3] = a4;
	assGrade_[4] = a5;
	assGrade_[5] = a6;
	assGrade_[6] = a7;
	assGrade_[7] = a8;
}

unsigned short Student::minOfFirst7Ass() const
{
	unsigned short minAssGrade = assGrade_[0];
	for (unsigned i = 1; i < noAssignments-1; i++) {
		if (minAssGrade < assGrade_[i])
			minAssGrade = assGrade_[i];
	}
	return minAssGrade;
}

unsigned short Student::totalPoints() const
{
	unsigned short sum = 0;

	for (unsigned i = 1; i < noAssignments; i++) {
		sum += assGrade_[i];
	}
	sum -= minOfFirst7Ass();
	sum += labExTotal_ + midterm_ + final_;
	return sum;
}

const char* Student::grade() const
{
	static char Grade[3];
	memset(Grade,0,3);
	unsigned pct = static_cast<unsigned>(100.f * totalPoints()/MaxTotalPoints);
	if (pct > 98) {
		strcpy(Grade,"A+");
		return Grade;
	}
	Grade[0] = pct > 59 && pct < 100 ? "DCBA"[pct/10-6] : 'F';
	Grade[1] = (pct % 10 == 9) ? '+' : ((pct % 10 == 0) ? '-': ' ');
	return Grade;
}

Review Questions

  1. The Class member, Student** students - what's your first guess on how this will work?
    If students was defined as Student*, how would your answer differ?
  2. The Class constructor allocates the array size to 40. How could we make this a variable?
  3. Does Class::getNoStudents() have to be a static member function? What are your options here?
  4. Is there a memory leak in this program?