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
- 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?
- The Class constructor allocates the array size to 40. How could we make this a variable?
- Does Class::getNoStudents() have to be a static member function? What are your options here?
- Is there a memory leak in this program?