optional · CSS study notes
Classes and Objects — Exam Practice (University Records System, Student Registration System)
Data Members of Class
- Instance data members: each object gets its own separate copy (e.g.,
length/widthin theRectangleexample below — everyRectangleobject has its own values) - Static data members: declared with
static, shared across all objects of the class — one copy total, not one per object (see the Classes Advanced page for fullstaticcoverage) - Initialization: modern C++ prefers initializing data members via the constructor's initializer list (
Rectangle(double l, double w) : length(l), width(w) {}) over assigning inside the constructor body — it's more efficient and required forconst/reference members
Member Functions
| Type | Purpose | Example |
|---|---|---|
| Accessor ("getter") | Reads a data member's value without modifying it | double getBalance() const { return balance; } |
| Mutator ("setter") | Modifies a data member's value in a controlled way | void deposit(double amt) { balance += amt; } |
| Utility/helper | Performs a computation using the object's data | double area() { return length * width; } |
| Constructor/Destructor | Special member functions for initialization/cleanup | see the Rectangle example below |
- Member functions defined inside the class body are implicitly
inline(compiler may substitute the call with the function body directly, avoiding call overhead — relevant for short, frequently-called functions) - Member functions can be marked
const(likegetBalance() constabove) to guarantee they don't modify the object — lets them be called onconstobjects too
Access Specifiers (Data Members & Member Functions visibility)
| Specifier | Accessible from |
|---|---|
private | Only within the same class (default for class) |
protected | Same class + any derived class, not from outside |
public | Anywhere the object is visible |
Note: struct defaults to public access; class defaults to private — a classic MCQ trap.
Basic worked example — Data Members, Member Functions, Constructor, Destructor together
#include <iostream>
using namespace std;
class Rectangle
{
private:
double length, width; // data members -- hidden from outside access
public:
Rectangle(double l, double w) : length(l), width(w) // constructor
{
cout << "Rectangle created.\n";
}
double area() { return length * width; } // member function
double perimeter() { return 2 * (length + width); }
~Rectangle() // destructor
{
cout << "Rectangle destroyed.\n";
}
};
int main()
{
Rectangle r(5, 3);
cout << "Area: " << r.area() << endl;
cout << "Perimeter: " << r.perimeter() << endl;
return 0; // destructor runs automatically here
}
Output:
Rectangle created.
Area: 15
Perimeter: 16
Rectangle destroyed.
- Class: a user-defined blueprint/template defining data members (attributes) and member functions (behavior)
- Object: a concrete instance of a class, occupying its own memory for data members
- Constructor: special member function automatically called on object creation, used to initialize data members; Destructor: automatically called on object destruction, used for cleanup (e.g., freeing dynamically allocated memory)
- Constructor types: default (no parameters, or all defaulted), parameterized (accepts arguments to set specific initial values), copy constructor (
ClassName(const ClassName& other)— builds a new object as a copy of an existing one; the compiler auto-generates a shallow-copy version unless you define your own) - Constructor overloading: a class may have multiple constructors with different parameter lists — the compiler picks the matching one based on the arguments supplied at creation
- Destructor rules: exactly one per class, takes no parameters, has no return type, and cannot be overloaded; for local (stack) objects, destructors fire automatically in reverse order of construction when they go out of scope
📝 Exam Practice: Quadratic Equation — Discriminant Calculator (Objects, Classes, Member Functions)
Q: Design a class to represent a quadratic equation of the form ax² + bx + c = 0, calculate its discriminant, and use it to classify the nature of the roots. Demonstrate the use of data members, a constructor, and member functions.
Concept recap: the discriminant is D = b² − 4ac. It classifies the roots without solving the equation:
| Discriminant | Nature of Roots |
|---|---|
D > 0 | Two distinct real roots |
D = 0 | One repeated real root (equal roots) |
D < 0 | Two complex (imaginary) roots |
Solution
#include <iostream>
#include <cmath>
using namespace std;
class QuadraticEquation
{
private:
double a, b, c; // coefficients -- private data members
double discriminant;
public:
// Parameterized constructor -- initializes coefficients via initializer list
QuadraticEquation(double a, double b, double c) : a(a), b(b), c(c)
{
discriminant = 0; // computed separately via calculateDiscriminant()
}
// Member function: computes and stores the discriminant
void calculateDiscriminant()
{
discriminant = (b * b) - (4 * a * c);
}
// Member function: uses the discriminant to describe the roots
void displayNatureOfRoots() const
{
cout << "Equation: " << a << "x^2 + " << b << "x + " << c << " = 0\n";
cout << "Discriminant (b^2 - 4ac) = " << discriminant << endl;
if (discriminant > 0)
cout << "Nature of roots: Two distinct real roots\n";
else if (discriminant == 0)
cout << "Nature of roots: One repeated real root\n";
else
cout << "Nature of roots: Two complex (imaginary) roots\n";
}
// Member function: computes and displays the actual roots
void displayRoots() const
{
if (discriminant >= 0)
{
double root1 = (-b + sqrt(discriminant)) / (2 * a);
double root2 = (-b - sqrt(discriminant)) / (2 * a);
cout << "Root 1 = " << root1 << ", Root 2 = " << root2 << endl;
}
else
{
double realPart = -b / (2 * a);
double imaginaryPart = sqrt(-discriminant) / (2 * a);
cout << "Root 1 = " << realPart << " + " << imaginaryPart << "i" << endl;
cout << "Root 2 = " << realPart << " - " << imaginaryPart << "i" << endl;
}
}
};
int main()
{
double a, b, c;
cout << "Enter coefficients a, b, c: ";
cin >> a >> b >> c;
QuadraticEquation eq(a, b, c); // object creation -- constructor runs
eq.calculateDiscriminant(); // member function call
eq.displayNatureOfRoots(); // member function call
eq.displayRoots(); // member function call
return 0;
}
Sample run (a=1, b=-5, c=6):
Enter coefficients a, b, c: 1 -5 6
Equation: 1x^2 + -5x + 6 = 0
Discriminant (b^2 - 4ac) = 1
Nature of roots: Two distinct real roots
Root 1 = 3, Root 2 = 2
Key reasoning points:
a,b,c, anddiscriminantare kept private — encapsulation, accessed only through the class's own member functions- The parameterized constructor initializes coefficients at object-creation time via the initializer list, rather than requiring a separate
setValues()call calculateDiscriminant()is a utility/helper member function — it performs a computation using the object's own data members and stores the result back into the object's state- Splitting
calculateDiscriminant(),displayNatureOfRoots(), anddisplayRoots()into separate member functions (rather than one giant function) demonstrates good single-responsibility design, which CSS examiners reward in "design a class" questions - Guard against
a == 0in a stronger answer: ifa = 0, the equation is not quadratic (it's linear) — mentioning this edge case shows deeper understanding
MCQ Trap: the discriminant formula is b² − 4ac, not b² + 4ac — a common transcription slip under exam pressure. Also remember: D = 0 means one repeated root, not "no roots."
Exam angle: this is a favorite short-question format ("design a class for X and compute Y using a member function") because it tests, in one small example, data members + constructor + member function + a real computation — exactly what examiners check for in Chapters 3–5 (Objects and Classes, Data Members, Member Functions).
📝 Exam Practice: University Records System (Student, Teacher, Course) — v2, improved
Q: A university maintains records for students, faculty, and academic courses using three classes, all stored in files:
- Student (ID, Name, Age, Address, Contact, Program, CGPA)
- Teacher (ID, Name, Age, Address, Highest Degree, Subjects, Salary)
- Course (Semester, Course Code, Student ID, Teacher ID, Grade)
(a) Draw a class diagram showing the three classes and their relationships.
(b) Write C++ programs to: add a student, add a course, add a teacher, find a student by CGPA, update a student.
(a) Class Diagram (relationships)
| Class | Attributes | Relationship |
|---|---|---|
| Person (base) | ID, Name, Age, Address | Shared by Student and Teacher — avoids duplicating these 4 fields in both |
| Student : Person | • Contact, Program, CGPA | 1 Student — many Courses (registers for) |
| Teacher : Person | • HighestDegree, Subjects, Salary | 1 Teacher — many Courses (teaches) |
| Course | Semester, CourseCode, StudentID, TeacherID, Grade | Associative/junction class linking Student ↔ Teacher (many-to-many) |
Course holds foreign keys (StudentID, TeacherID) — the standard way to model a many-to-many relationship using a linking entity, the same pattern as a junction table in a database ER diagram.
What changed from v1 (and why)
| Improvement | Reason |
|---|---|
Added a Person base class; Student/Teacher inherit from it | v1 duplicated ID/Name/Age/Address in both classes — inheritance removes that duplication and is what examiners look for in a "design classes" question |
Made all data members private, added getId()/getCgpa() accessors | v1 left everything public — direct field access breaks encapsulation, a core OOP principle graders check |
| Added duplicate-ID check before inserting a student | v1 would silently create two records with the same ID — basic data-integrity issue |
Added CGPA range validation (0.0–4.0) in getdata() | v1 accepted any float, including impossible values like -5 or 12 |
| Added a "List All Students" option | v1 had no way to view all records at once, only single-record lookup |
| Deliberately did NOT add virtual functions here | See note below — this file uses raw binary I/O, where virtual functions are unsafe |
⚠️ Important constraint — why no polymorphism in this example:
This program writes whole objects to disk with fout.write((char*)&s, sizeof(Student)). If Student had any virtual function, the compiler would add a hidden vtable pointer to every object's memory layout. That pointer is a memory address, valid only within one running program — writing it to a file and reading it back (even in the same program, let alone a future run) produces a dangling/meaningless pointer and undefined behavior. Rule of thumb: classes written via raw binary I/O must stay free of virtual functions — plain data + non-virtual methods only. (The Student Registration System example below shows the opposite case: no file I/O, so virtual functions are used freely for polymorphism.)
(b) Solution — file-based CRUD using fstream
#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;
const int MAXLEN = 15;
// ---------- Shared base: Person (NO virtual functions -- safe for raw binary I/O) ----------
class Person
{
protected:
int id;
char name[MAXLEN];
int age;
char address[MAXLEN];
public:
Person() : id(0), age(0) { name[0] = '\0'; address[0] = '\0'; }
int getId() const { return id; }
void getdata()
{
cout << "Enter ID: "; cin >> id;
cout << "Enter Name: "; cin >> name;
cout << "Enter Age: "; cin >> age;
cout << "Enter Address: "; cin >> address;
}
void showdata() const
{
cout << id << "\t" << name << "\t" << age << "\t" << address;
}
};
class Student : public Person
{
private:
char contact[MAXLEN];
char program[MAXLEN];
float cgpa;
public:
Student() : Person(), cgpa(0) { contact[0] = '\0'; program[0] = '\0'; }
void getdata()
{
Person::getdata();
cout << "Enter Contact: "; cin >> contact;
cout << "Enter Program: "; cin >> program;
do {
cout << "Enter CGPA (0.0 - 4.0): "; cin >> cgpa;
if (cgpa < 0 || cgpa > 4.0f) cout << "Invalid CGPA, try again.\n";
} while (cgpa < 0 || cgpa > 4.0f);
}
void showdata() const
{
Person::showdata();
cout << "\t" << contact << "\t" << program << "\t" << cgpa << endl;
}
float getCgpa() const { return cgpa; }
};
class Teacher : public Person
{
private:
char highestDegree[MAXLEN];
char subjects[MAXLEN];
float salary;
public:
Teacher() : Person(), salary(0) { highestDegree[0] = '\0'; subjects[0] = '\0'; }
void getdata()
{
Person::getdata();
cout << "Enter Highest Degree: "; cin >> highestDegree;
cout << "Enter Subjects: "; cin >> subjects;
cout << "Enter Salary: "; cin >> salary;
}
void showdata() const
{
Person::showdata();
cout << "\t" << highestDegree << "\t" << subjects << "\t" << salary << endl;
}
};
class Course
{
private:
int semester;
char courseCode[MAXLEN];
int studentID;
int teacherID;
char grade[5];
public:
void getdata()
{
cout << "Enter Semester: "; cin >> semester;
cout << "Enter Course Code: "; cin >> courseCode;
cout << "Enter Student ID: "; cin >> studentID;
cout << "Enter Teacher ID: "; cin >> teacherID;
cout << "Enter Grade: "; cin >> grade;
}
void showdata() const
{
cout << semester << "\t" << courseCode << "\t" << studentID
<< "\t" << teacherID << "\t" << grade << endl;
}
};
bool studentIdExists(int id)
{
Student s;
ifstream fin("students.dat", ios::binary);
while (fin.read((char*)&s, sizeof(Student)))
if (s.getId() == id) { fin.close(); return true; }
fin.close();
return false;
}
// ---------- i. Add a Student ----------
void addStudent()
{
Student s;
s.getdata();
if (studentIdExists(s.getId()))
{
cout << "Error: Student ID already exists.\n";
return;
}
ofstream fout("students.dat", ios::app | ios::binary);
fout.write((char*)&s, sizeof(Student));
fout.close();
cout << "Student added successfully.\n";
}
// ---------- ii. Add a Course ----------
void addCourse()
{
Course c;
c.getdata();
ofstream fout("courses.dat", ios::app | ios::binary);
fout.write((char*)&c, sizeof(Course));
fout.close();
cout << "Course added successfully.\n";
}
// ---------- iv. Add a Teacher ----------
void addTeacher()
{
Teacher t;
t.getdata();
ofstream fout("teachers.dat", ios::app | ios::binary);
fout.write((char*)&t, sizeof(Teacher));
fout.close();
cout << "Teacher added successfully.\n";
}
// ---------- iii. Find a Student by CGPA ----------
void findStudentByCGPA(float targetCGPA)
{
Student s;
ifstream fin("students.dat", ios::binary);
bool found = false;
while (fin.read((char*)&s, sizeof(Student)))
{
if (s.getCgpa() == targetCGPA)
{
s.showdata();
found = true;
}
}
fin.close();
if (!found) cout << "No student found with CGPA " << targetCGPA << endl;
}
// ---------- v. Update a Student ----------
void updateStudent(int searchID)
{
fstream file("students.dat", ios::in | ios::out | ios::binary);
Student s;
bool found = false;
while (file.read((char*)&s, sizeof(Student)))
{
if (s.getId() == searchID)
{
found = true;
cout << "Enter updated data for student ID " << searchID << ":\n";
Student updated;
updated.getdata();
file.seekp(-(int)sizeof(Student), ios::cur);
file.write((char*)&updated, sizeof(Student));
break;
}
}
file.close();
if (!found) cout << "Student ID " << searchID << " not found.\n";
}
// ---------- List All Students (new in v2) ----------
void listAllStudents()
{
Student s;
ifstream fin("students.dat", ios::binary);
cout << "\n--- All Students ---\n";
while (fin.read((char*)&s, sizeof(Student)))
s.showdata();
fin.close();
}
int main()
{
int option;
do
{
cout << "\n--- University Records System ---\n";
cout << "1. Add a Student\n2. Add a Course\n3. Add a Teacher\n";
cout << "4. Find Student by CGPA\n5. Update a Student\n6. List All Students\n0. Exit\nEnter option: ";
cin >> option;
switch (option)
{
case 1: addStudent(); break;
case 2: addCourse(); break;
case 3: addTeacher(); break;
case 4:
{
float cgpa;
cout << "Enter CGPA to search: ";
cin >> cgpa;
findStudentByCGPA(cgpa);
break;
}
case 5:
{
int id;
cout << "Enter Student ID to update: ";
cin >> id;
updateStudent(id);
break;
}
case 6: listAllStudents(); break;
case 0: cout << "Exiting...\n"; break;
default: cout << "Invalid option.\n";
}
} while (option != 0);
return 0;
}
Key reasoning points:
- Records are still written as raw binary structs — enables direct positional access (
seekp/seekg) for in-place updates, which text files can't reliably support Personis now a genuine base class shared byStudentandTeacher— inheritance without virtual functions is completely safe for binary I/O, since it adds no vtable pointer to the memory layout- Encapsulation (
private+ accessor methods) and validation (CGPA range, duplicate ID) turn this from a "just compiles" answer into a more complete, production-minded one — the kind of detail that separates a good CSS answer from an excellent one
Exam angle: if asked "can this design use polymorphism," the correct answer is not simply yes — a strong answer explains why binary-file-backed classes should avoid virtual functions (vtable pointers aren't portable across writes/reads), which shows deeper understanding than blindly adding virtual everywhere.
📝 Exam Practice: Student Registration System (Inheritance + Composition + Polymorphism) — v2, improved
Q: Suppose you are trying to build a Student Registration System using an object-oriented approach. The objective is to store information for registration of students and their course results. Design the following classes with suitable attributes, each having getdata() and showdata() member functions along with suitable constructors: Person, Teacher, Student, Course, Section, Allocation (containing information about allocation of a course to a teacher in a semester), Registration (containing information about registration of a student to a course, including course result).
Design approach
| Relationship | Classes involved | Why |
|---|---|---|
| Inheritance ("is-a") | Teacher : Person, Student : Person | Both share name/age/CNIC — reuse via a common base class |
| Composition ("has-a") | Allocation contains Course + Teacher + Section | An allocation record is built from existing entities, not a type of any of them |
| Composition ("has-a") | Registration contains Student + Course + result data | A registration record links a student to a course and stores their grade |
What changed from v1 (and why)
| Improvement | Reason |
|---|---|
Made getdata()/showdata() virtual in Person, added override in derived classes | v1 had these as ordinary functions — calling them through a Person* would always run Person's version, not the derived one. This example has no file I/O, so virtual functions are completely safe to use here |
Added a virtual ~Person() destructor | Mandatory whenever a base class is used polymorphically through pointers — without it, delete on a Person* pointing to a Student only runs ~Person(), leaking the derived part (a very common CSS exam trap) |
Introduced vector<Person*> roster in main() | v1 could only create and show one Student or one Teacher per run — a single polymorphic container now holds both types together and displays them uniformly |
| Menu-driven loop instead of one-shot choice | v1 exited after a single action; v2 lets you add multiple students/teachers, then view them all |
Solution
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// ---------- Base class ----------
class Person
{
protected:
string name;
int age;
string cnic;
public:
Person() : name(""), age(0), cnic("") {}
Person(string n, int a, string c) : name(n), age(a), cnic(c) {}
virtual void getdata()
{
cout << "Enter name: "; cin >> name;
cout << "Enter age: "; cin >> age;
cout << "Enter CNIC: "; cin >> cnic;
}
virtual void showdata() const
{
cout << "Name: " << name << ", Age: " << age << ", CNIC: " << cnic << endl;
}
virtual ~Person() {} // required for correct cleanup through base-class pointers
};
// ---------- Teacher : Person ----------
class Teacher : public Person
{
private:
string employeeId;
string department;
public:
Teacher() : Person(), employeeId(""), department("") {}
void getdata() override
{
Person::getdata();
cout << "Enter Employee ID: "; cin >> employeeId;
cout << "Enter Department: "; cin >> department;
}
void showdata() const override
{
Person::showdata();
cout << "Employee ID: " << employeeId << ", Department: " << department << endl;
}
};
// ---------- Student : Person ----------
class Student : public Person
{
private:
string rollNo;
string program;
public:
Student() : Person(), rollNo(""), program("") {}
void getdata() override
{
Person::getdata();
cout << "Enter Roll No: "; cin >> rollNo;
cout << "Enter Program: "; cin >> program;
}
void showdata() const override
{
Person::showdata();
cout << "Roll No: " << rollNo << ", Program: " << program << endl;
}
};
// ---------- Course ----------
class Course
{
private:
string courseCode, courseTitle;
int creditHours;
public:
Course() : courseCode(""), courseTitle(""), creditHours(0) {}
void getdata()
{
cout << "Enter Course Code: "; cin >> courseCode;
cout << "Enter Course Title: "; cin >> courseTitle;
cout << "Enter Credit Hours: "; cin >> creditHours;
}
void showdata() const
{
cout << "Course: " << courseCode << " - " << courseTitle
<< " (" << creditHours << " CH)" << endl;
}
};
// ---------- Section ----------
class Section
{
private:
string sectionId, semester;
public:
void getdata()
{
cout << "Enter Section ID: "; cin >> sectionId;
cout << "Enter Semester: "; cin >> semester;
}
void showdata() const
{
cout << "Section: " << sectionId << ", Semester: " << semester << endl;
}
};
// ---------- Allocation (Course + Teacher + Section) ----------
class Allocation
{
private:
Course course;
Teacher teacher;
Section section;
public:
void getdata()
{
cout << "-- Course --\n"; course.getdata();
cout << "-- Teacher --\n"; teacher.getdata();
cout << "-- Section --\n"; section.getdata();
}
void showdata() const
{
course.showdata();
teacher.showdata();
section.showdata();
}
};
// ---------- Registration (Student + Course + Result) ----------
class Registration
{
private:
Student student;
Course course;
float marksObtained;
char grade;
void calculateGrade()
{
if (marksObtained >= 90) grade = 'A';
else if (marksObtained >= 80) grade = 'B';
else if (marksObtained >= 70) grade = 'C';
else if (marksObtained >= 60) grade = 'D';
else grade = 'F';
}
public:
Registration() : marksObtained(0), grade(' ') {}
void getdata()
{
cout << "-- Student --\n"; student.getdata();
cout << "-- Course --\n"; course.getdata();
cout << "Enter Marks Obtained: "; cin >> marksObtained;
calculateGrade();
}
void showdata() const
{
student.showdata();
course.showdata();
cout << "Marks: " << marksObtained << ", Grade: " << grade << endl;
}
};
// ---------- main ----------
int main()
{
vector<Person*> roster; // one container, mixed Student/Teacher objects -- classic polymorphism demo
int choice;
do
{
cout << "\n1. Add a Student (to roster)\n2. Add a Teacher (to roster)\n"
<< "3. Show entire roster (polymorphic display)\n4. Register a student for a course\n"
<< "5. Allocate a course to a teacher\n0. Exit\nEnter choice: ";
cin >> choice;
if (choice == 1)
{
Person* p = new Student();
p->getdata(); // resolves to Student::getdata() at runtime
roster.push_back(p);
}
else if (choice == 2)
{
Person* p = new Teacher();
p->getdata(); // resolves to Teacher::getdata() at runtime
roster.push_back(p);
}
else if (choice == 3)
{
cout << "\n--- Roster (Students and Teachers together) ---\n";
for (Person* p : roster)
p->showdata(); // each call dispatches to the correct override
}
else if (choice == 4)
{
Registration reg;
reg.getdata();
cout << "\n--- Registration Summary ---\n";
reg.showdata();
}
else if (choice == 5)
{
Allocation alloc;
alloc.getdata();
cout << "\n--- Allocation Summary ---\n";
alloc.showdata();
}
} while (choice != 0);
for (Person* p : roster) delete p; // virtual destructor ensures the correct derived dtor runs for each
return 0;
}
Key reasoning points:
Personis the shared base class —TeacherandStudentboth inherit from it, and now theirgetdata()/showdata()arevirtual, enabling true runtime polymorphism: avector<Person*>can hold a mix of both types and call the correct version automatically- The
virtual ~Person()destructor is not optional here — omitting it while deleting derived objects through aPerson*is undefined behavior (skips the derived class's cleanup) and a frequently tested CSS exam trap CourseandSectionremain composed (not inherited) intoAllocation/Registration— "has-a," not "is-a"- This design is only safe to make polymorphic because there's no raw binary file I/O here — contrast with the University Records System above, where virtual functions are deliberately avoided for exactly that reason
Reusable approach for any "design a system for X" CSS question:
- Identify the "nouns" in the question — these become your classes
- Decide "is-a" (inheritance) vs "has-a" (composition) for each relationship
- List realistic attributes for each class (3–5 is normal for exam answers)
- Add the required methods — usually
getdata()/showdata()plus constructors - Decide whether polymorphism is actually needed: if objects are ever stored/manipulated through a base-class pointer or a mixed-type container, make the shared methods
virtualand add avirtualdestructor; if the class will be written to disk as raw binary, avoidvirtualentirely - When overriding a method in a derived class, call the base version first (
Person::getdata()), then add child-specific fields - Write a minimal
main()proving the design works
Exam angle: examiners commonly test whether students know when to reach for virtual functions versus when they're unnecessary or actively harmful (as with binary file I/O) — showing that judgment, not just syntax, earns the higher marks.
📜 Past-Paper Questions & MCQs (CSS 2016–2026)
2016 · Paper-I · Q2(c) · 8 marks
Q. Student Registration System: define Person, Teacher, Student, Course, Section, Allocation and Registration classes in C++ with attributes, getdata() and showdata(), and constructors.
Ans.
class Person {
protected: char name[30]; int age;
public:
Person(const char *n = "", int a = 0) { strcpy(name, n); age = a; }
void getdata() { cout << "Name: "; cin >> name; cout << "Age: "; cin >> age; }
void showdata() { cout << name << " " << age << endl; }
};
class Teacher : public Person {
int empId; char dept[20];
public:
Teacher() : Person(), empId(0) { strcpy(dept, ""); }
void getdata() { Person::getdata(); cout << "EmpId, Dept: "; cin >> empId >> dept; }
void showdata() { Person::showdata(); cout << empId << " " << dept << endl; }
};
class Student : public Person {
int regNo; char program[20];
public:
Student() : Person(), regNo(0) { strcpy(program, ""); }
void getdata() { Person::getdata(); cout << "RegNo, Program: "; cin >> regNo >> program; }
void showdata() { Person::showdata(); cout << regNo << " " << program << endl; }
};
class Course {
char code[10], title[30]; int crHours;
public:
Course() : crHours(0) { code[0] = title[0] = '\0'; }
void getdata() { cin >> code >> title >> crHours; }
void showdata() { cout << code << " " << title << " " << crHours << endl; }
};
class Section {
char name[10]; char courseCode[10];
public:
Section() { name[0] = courseCode[0] = '\0'; }
void getdata() { cin >> name >> courseCode; }
void showdata() { cout << name << " " << courseCode << endl; }
};
class Allocation { // course allocated to a teacher in a semester
int empId; char courseCode[10]; char semester[10];
public:
Allocation() : empId(0) { courseCode[0] = semester[0] = '\0'; }
void getdata() { cin >> empId >> courseCode >> semester; }
void showdata() { cout << empId << " " << courseCode << " " << semester << endl; }
};
class Registration { // student registered in a course, with result
int regNo; char courseCode[10]; float marks; char grade;
public:
Registration() : regNo(0), marks(0), grade('-') { courseCode[0] = '\0'; }
void getdata() { cin >> regNo >> courseCode >> marks >> grade; }
void showdata() { cout << regNo << " " << courseCode << " " << marks << " " << grade << endl; }
};
TeacherandStudentinherit fromPerson.AllocationandRegistrationconnect teachers and students to courses (associations).
2016 · Paper-I · Q3(c) · 8 marks
Q. Library Information System: describe the classes, data members and member functions to track issued and returned books and calculate fines.
Ans.
- Person (base):
name,id,phone;getdata(),showdata(). - Student : Person:
rollNo,program,booksIssued. - Teacher : Person:
dept,designation. - Book:
isbn,title,author,copiesAvailable;isAvailable(),showdata(). - IssueBook:
memberId,isbn,issueDate,dueDate,returnDate;issue(),returnBook(),calculateFine().
class IssueBook {
int memberId; char isbn[15];
int issueDay, dueDay, returnDay; // days counted from a fixed date
static const int finePerDay = 10;
public:
int calculateFine() {
return (returnDay > dueDay) ? (returnDay - dueDay) * finePerDay : 0;
}
};
- Fine rule: fine = (return date − due date) × fine per day, only when the book is late.
2016 · Paper-I · Q4(c) · 8 marks
Q. Medical Store software: define classes such as Person, Customer, Salesman and Purchase with attributes, using inheritance where suitable.
Ans.
class Person {
protected: char name[30]; int age; char phone[15];
};
class Customer : public Person { // is-a Person
int customerId; char address[50];
};
class Salesman : public Person { // is-a Person
int empId; float salary;
};
class Medicine {
int code; char name[30]; float price; int stock; char expiry[11];
};
class Purchase { // has-a Customer, Salesman and Medicine
int invoiceNo; int customerId; int salesmanId;
int medicineCode; int quantity; char date[11]; float total;
};
CustomerandSalesmanshare the common attributes ofPerson.Purchaselinks the other classes by their ids (association).
2020 · Paper-I · Q5(a) · 5 marks
Q. A university keeps records for Student (ID, Name, Age, Address, Contact, Program, CGPA), Teacher (ID, Name, Age, Address, Highest Degree, Subjects, Salary) and Course (Semester, Course Code, Student ID, Teacher ID, Grade). Draw a class diagram with relationships.
Ans.
classDiagram
class Student {
+int ID
+string Name
+int Age
+string Address
+string Contact
+string Program
+float CGPA
}
class Teacher {
+int ID
+string Name
+int Age
+string Address
+string HighestDegree
+string Subjects
+float Salary
}
class Course {
+string Semester
+string CourseCode
+int StudentID
+int TeacherID
+string Grade
}
Student "1" --> "*" Course : enrolls in
Teacher "1" --> "*" Course : teaches
- Relationships: a Course record links one student and one teacher (association). One student can have many Course records, and one teacher can teach many.