C++: Practice: OOP Comprehensive

Last updated: 2026-08-26

In the previous 35 lessons, we've covered many aspects of C++.

Now, it's time to put it all together.

In this lesson, we'll build a complete student management system — from requirements analysis to code implementation, experiencing real software development.


1. Project Requirements Analysis

(1) 1.1 Functional Requirements

The student management system we're building has the following features:

Feature Module Specific Functions
Student Management Add, delete, modify, search students
Grade Management Enter grades, calculate averages, ranking
Data Persistence Save to file, load from file
User Interface Menu-driven console interface

(2) 1.2 Class Design

Based on the requirements, we need to design the following classes:

TEXT 📖 Display only
Student (Base class)
 ↑ Inherits
UndergraduateStudent (Undergraduate)
GraduateStudent (Graduate student)

Course (Course class)
Grade (Grade class)

ManagementSystem (Management system class)
 - vector<Student*> students
 - vector<Course> courses


2. Basic Version Implementation

(1) 2.1 Student Class Design

Example: Student Class Basic Version (Difficulty ⭐⭐)

TEXT 📖 Display only
#include <iostream>
#include <string>
#include <vector>

// Student base class
class Student {
protected:
	std::string id; // Student ID
	std::string name; // Name
	int age; // Age
	std::string major; // Major

public:
	// Constructor
	Student(const std::string& id, const std::string& name, int age, const std::string& major)
	: id(id), name(name), age(age), major(major) {}
	
	// Virtual function: display info
	virtual void display() const {
		std::cout << "Student ID: " << id << std::endl;
		std::cout << "Name: " << name << std::endl;
		std::cout << "Age: " << age << std::endl;
		std::cout << "Major: " << major << std::endl;
	}
	
	// Virtual destructor
	virtual ~Student() {}
	
	// Getter
	std::string getId() const { return id; }
	std::string getName() const { return name; }
};

// Undergraduate class
class UndergraduateStudent : public Student {
private:
	int year; // Year (1-4)

public:
	UndergraduateStudent(const std::string& id, const std::string& name, 
					int age, const std::string& major, int year)
	: Student(id, name, age, major), year(year) {}
	
	void display() const override {
		Student::display();
		std::cout << "Year: " << year << std::endl;
		std::cout << "Type: Undergraduate" << std::endl;
	}
};

// Graduate student class
class GraduateStudent : public Student {
private:
	std::string advisor; // Advisor

public:
	GraduateStudent(const std::string& id, const std::string& name,
				int age, const std::string& major, const std::string& advisor)
	: Student(id, name, age, major), advisor(advisor) {}
	
	void display() const override {
		Student::display();
		std::cout << "Advisor: " << advisor << std::endl;
		std::cout << "Type: Graduate Student" << std::endl;
	}
};

(2) 2.2 Management System Class

Example: Management System Basic Version (Difficulty ⭐⭐⭐)

▶ Example 1: Using STL Containers (Difficulty ⭐)

CPP
class ManagementSystem {
private:
	std::vector<Student*> students; // Student list (polymorphism)

public:
	// Add student
	void addStudent(Student* student) {
		students.push_back(student);
		std::cout << "Added successfully!" << std::endl;
	}
	
	// Find student
	Student* findStudent(const std::string& id) {
		for (auto s : students) {
			if (s->getId() == id) {
				return s;
			}
		}
		return nullptr;
	}
	
	// Display all students
	void displayAll() const {
		if (students.empty()) {
			std::cout << "No student information available" << std::endl;
			return;
		}
		
		for (auto s : students) {
			s->display();
			std::cout << "-------------------" << std::endl;
		}
	}
	
	// Destructor: free memory
	~ManagementSystem() {
		for (auto s : students) {
			delete s;
		}
	}
};

// Test code
int main() {
	ManagementSystem sys;
	
	// Add undergraduate
	sys.addStudent(new UndergraduateStudent("001", "Zhang San", 20, "Computer Science", 3));
	sys.addStudent(new GraduateStudent("002", "Li Si", 24, "Software Engineering", "Prof. Wang"));
	
	// Display all students
	sys.displayAll();
	
	return 0;
}
▶ Try it Yourself

Output:

TEXT 📖 Display only
Added successfully!
No student information available
-------------------

Run result:

TEXT 📖 Display only
Added successfully!
Added successfully!
Student ID: 001
Name: Zhang San
Age: 20
Major: Computer Science
Year: 3
Type: Undergraduate
-------------------
Student ID: 002
Name: Li Si
Age: 24
Major: Software Engineering
Advisor: Prof. Wang
Type: Graduate Student
-------------------


3. Complete Version Implementation

(1) 3.1 Adding More Features

Now, let's add more features to the system:

Feature Implementation
Delete student Delete by student ID
Modify info Find by student ID, then modify
Grade management Add a Grade class
Save to file Use ofstream to write file
Load from file Use ifstream to read file

(2) 3.2 Grade Class Design

TEXT 📖 Display only
// Grade class
### ▶ Example 2: Object-Oriented Programming Demo (Difficulty ⭐)

class Grade {
private:
	std::string courseId; // Course ID
	std::string courseName; // Course name
	double score; // Score

public:
	Grade(const std::string& courseId, const std::string& courseName, double score)
	: courseId(courseId), courseName(courseName), score(score) {}
	
	void display() const {
		std::cout << courseName << ": " << score << " points" << std::endl;
	}
	
	double getScore() const { return score; }
};

// Add grade-related methods to the Student class
class Student {
	// ... other members ...
	std::vector<Grade> grades; // Grade list

public:
	void addGrade(const Grade& grade) {
		grades.push_back(grade);
	}
	
	void displayGrades() const {
		if (grades.empty()) {
			std::cout << "No grades available" << std::endl;
			return;
		}
		
		std::cout << name << "'s grades:" << std::endl;
		for (const auto& g : grades) {
			g.display();
		}
	}
	
	double getAverage() const {
		if (grades.empty()) return 0.0;
		
		double sum = 0;
		for (const auto& g : grades) {
			sum += g.getScore();
		}
		return sum / grades.size();
	}
};

(3) 3.3 File Operations

Save student information to file:

CPP
void saveToFile(const std::string& filename) {
	std::ofstream file(filename);
	if (!file) {
		std::cout << "Cannot open file" << std::endl;
		return;
	}
	
	for (auto s : students) {
		file << s->getId() << ","
			<< s->getName() << ","
			<< s->getAge() << std::endl;
	}
	
	file.close();
	std::cout << "Saved successfully!" << std::endl;
}

Load from file:

TEXT 📖 Display only
void loadFromFile(const std::string& filename) {
	std::ifstream file(filename);
	if (!file) {
		std::cout << "Cannot open file" << std::endl;
		return;
	}
	
	std::string id, name, ageStr;
	while (std::getline(file, id, ',')) {
		std::getline(file, name, ',');
		std::getline(file, ageStr);
		int age = std::stoi(ageStr);
		
		// Create student object (simplified; should distinguish undergraduate/graduate)
		students.push_back(new UndergraduateStudent(id, name, age, "Unknown", 1));
	}
	
	file.close();
	std::cout << "Loaded successfully!" << std::endl;
}


4. Menu Interface Implementation

(1) 4.1 Main Menu

CPP
void showMenu() {
	std::cout << "\n===== Student Management System =====" << std::endl;
	std::cout << "1. Add student" << std::endl;
	std::cout << "2. Find student" << std::endl;
	std::cout << "3. Display all students" << std::endl;
	std::cout << "4. Enter grades" << std::endl;
	std::cout << "5. Save data" << std::endl;
	std::cout << "6. Load data" << std::endl;
	std::cout << "0. Exit" << std::endl;
	std::cout << "=====================================" << std::endl;
	std::cout << "Choose: ";
}

int main() {
	ManagementSystem sys;
	int choice;
	
	do {
		showMenu();
		std::cin >> choice;
		
		switch (choice) {
		case 1:
			// Add student
			break;
		case 2:
			// Find student
			break;
		case 3:
			sys.displayAll();
			break;
		case 0:
			std::cout << "Goodbye!" << std::endl;
			break;
		default:
			std::cout << "Invalid choice" << std::endl;
		}
	} while (choice != 0);
	
	return 0;
}


5. Project Extension Suggestions

(1) 5.1 Feature Extensions

Feature Difficulty Description
Grade Statistics ⭐⭐ Calculate averages, rankings
Data Validation ⭐⭐ Check input validity
Exception Handling ⭐⭐⭐ Use try-catch for errors
GUI ⭐⭐⭐⭐ Use Qt or wxWidgets
Database ⭐⭐⭐⭐ Use SQLite or MySQL

(2) 5.2 Code Optimization

Optimization Description
Smart Pointers Use unique_ptr for memory management
Const Correctness Use const wherever possible
Exception Handling Use try-catch for file errors
Operator Overloading Overload << for output

▶ Example 3: Simple Class Inheritance Hierarchy (Difficulty ⭐)

CPP
#include <iostream>
#include <string>

class Animal {
public:
    std::string name;
    Animal(const std::string& n) : name(n) {}
    virtual void speak() const = 0;
    virtual ~Animal() {}
};

class Dog : public Animal {
public:
    Dog(const std::string& n) : Animal(n) {}
    void speak() const override {
        std::cout << name << ": Woof!" << std::endl;
    }
};

class Cat : public Animal {
public:
    Cat(const std::string& n) : Animal(n) {}
    void speak() const override {
        std::cout << name << ": Meow!" << std::endl;
    }
};

int main() {
    Dog dog("Wangcai");
    Cat cat("Mimi");
    dog.speak();
    cat.speak();
    return 0;
}
▶ Try it Yourself

Output:

TEXT 📖 Display only
: Woof!
: Meow!

❓ FAQ

Q: Why use pointers to store students? A: To achieve polymorphism. Using vector<Student> would cause object slicing, so only base class methods could be called.


Q: What about memory leaks? A: Use smart pointers (unique_ptr) to automatically manage memory — no need for manual delete.


Q: How should I design the file format? A: You can use: - CSV format: simple, but limited functionality - JSON format: powerful, requires third-party library - Binary format: efficient, but not human-readable


Q How to handle Chinese characters?
A C++ has limited Chinese support. Suggestions: - Use wstring + wcout - Or use a third-party library (e.g., iconv) - Or only store pinyin/English

📖 Summary

Knowledge Point Key Takeaway
Class Design Base class + derived class, reflecting inheritance
Polymorphism Use pointers/references to call virtual functions
File Operations ofstream for writing, ifstream for reading
Memory Management Destructor frees memory (or use smart pointers)
Menu Interface do-while + switch

Study suggestions:


📝 Exercises

  1. Basic (Difficulty ⭐): Define a Book class (title, author, price), create 3 objects and output their properties.

  2. Intermediate (Difficulty ⭐⭐): Implement an inheritance hierarchy: Shape (base class, pure virtual function area()) → Circle and Rectangle derived classes. Call area() polymorphically.

  3. Challenge (Difficulty ⭐⭐⭐): Implement an "Observer pattern": Subject class maintains an Observer list, Observer is an abstract base class. When Subject state changes, notify all Observers.



Phase 5 complete! Next: Phase 6 (Advanced STL)

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏