C++: تمرين: البرمجة كائنية التوجه الشامل

آخر تحديث: 2026-08-26

في الدروس الـ 35 السابقة، غطينا جوانب عديدة من C++.

الآن، حان وقت الجمع بين كل شيء.

في هذا الدرس، سنبنى نظام إدارة طلاب كامل — من تحليل المتطلبات إلى تنفيذ الكود، مع تجربة تطوير البرمجيات الحقيقية.


1. تحليل متطلبات المشروع

(1) 1.1 المتطلبات الوظيفية

نظام إدارة الطلاب الذي نبناه له الميزات التالية:

وحدة الميزات الوظائف المحددة
إدارة الطلاب إضافة، حذف، تعديل، بحث الطلاب
إدارة الدرجات إدخال الدرجات، حساب المتوسطات، الترتيب
الثبات البياني حفظ في ملف، تحميل من ملف
واجهة المستخدم واجهة طرفية بقوائم

(2) 1.2 تصميم الأصناف

بناءً على المتطلبات، نحتاج لتصميم الأصناف التالية:

TEXT 📖 للعرض فقط
Student (الصنف الأساسي)
 ↑ يرث
UndergraduateStudent (طالب جامعي)
GraduateStudent (طالب دراسات عليا)

Course (صنف المقرر)
Grade (صنف الدرجة)

ManagementSystem (صنف نظام الإدارة)
 - vector<Student*> students
 - vector<Course> courses


2. تنفيذ النسخة الأساسية

(1) 2.1 تصميم صنف الطالب

مثال: صنف الطالب النسخة الأساسية (الصعوبة ⭐⭐)

TEXT 📖 للعرض فقط
#include <iostream>
#include <string>
#include <vector>

// صنف الطالب الأساسي
class Student {
protected:
	std::string id; // رقم الطالب
	std::string name; // الاسم
	int age; // العمر
	std::string major; // التخصص

public:
	// المُنشئ
	Student(const std::string& id, const std::string& name, int age, const std::string& major)
	: id(id), name(name), age(age), major(major) {}
	
	// دالة افتراضية: عرض المعلومات
	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 ~Student() {}
	
	// الحاصلات
	std::string getId() const { return id; }
	std::string getName() const { return name; }
};

// صنف الطالب الجامعي
class UndergraduateStudent : public Student {
private:
	int 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;
	}
};

// صنف طالب الدراسات العليا
class GraduateStudent : public Student {
private:
	std::string 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 صنف نظام الإدارة

مثال: نظام الإدارة النسخة الأساسية (الصعوبة ⭐⭐⭐)

▶ مثال 1: استخدام حاويات STL (الصعوبة ⭐)

CPP
class ManagementSystem {
private:
	std::vector<Student*> students; // قائمة الطلاب (تعدد الأشكال)

public:
	// إضافة طالب
	void addStudent(Student* student) {
		students.push_back(student);
		std::cout << "Added successfully!" << std::endl;
	}
	
	// البحث عن طالب
	Student* findStudent(const std::string& id) {
		for (auto s : students) {
			if (s->getId() == id) {
				return s;
			}
		}
		return nullptr;
	}
	
	// عرض جميع الطلاب
	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;
		}
	}
	
	// المدمر: تحرير الذاكرة
	~ManagementSystem() {
		for (auto s : students) {
			delete s;
		}
	}
};

// كود الاختبار
int main() {
	ManagementSystem sys;
	
	// إضافة طالب جامعي
	sys.addStudent(new UndergraduateStudent("001", "Zhang San", 20, "Computer Science", 3));
	sys.addStudent(new GraduateStudent("002", "Li Si", 24, "Software Engineering", "Prof. Wang"));
	
	// عرض جميع الطلاب
	sys.displayAll();
	
	return 0;
}
▶ جرّب الكود

الخرج:

TEXT 📖 للعرض فقط
Added successfully!
No student information available
-------------------

نتيجة التشغيل:

TEXT 📖 للعرض فقط
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. تنفيذ النسخة الكاملة

(1) 3.1 إضافة ميزات أخرى

الآن، لنضيف ميزات أخرى للنظام:

الميزة التنفيذ
حذف طالب حذف برقم الطالب
تعديل المعلومات البحث برقم الطالب، ثم التعديل
إدارة الدرجات إضافة صنف Grade
الحفظ في ملف استخدام ofstream لكتابة ملف
التحميل من ملف استخدام ifstream لقراءة ملف

(2) 3.2 تصميم صنف الدرجة

TEXT 📖 للعرض فقط
// صنف الدرجة
### ▶ مثال 2: عرض البرمجة كائنية التوجه (الصعوبة ⭐)

class Grade {
private:
	std::string courseId; // رقم المقرر
	std::string courseName; // اسم المقرر
	double 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; }
};

// إضافة طرق متعلقة بالدرجات لصنف Student
class Student {
	// ... أعضاء آخرون ...
	std::vector<Grade> grades; // قائمة الدرجات

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 عمليات الملفات

حفظ معلومات الطلاب في ملف:

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;
}

التحميل من ملف:

TEXT 📖 للعرض فقط
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);
		
		// إنشاء كائن طالب (مبسط؛ يجب التمييز بين جامعي/دراسات عليا)
		students.push_back(new UndergraduateStudent(id, name, age, "Unknown", 1));
	}
	
	file.close();
	std::cout << "Loaded successfully!" << std::endl;
}


4. تنفيذ واجهة القائمة

(1) 4.1 القائمة الرئيسية

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:
			// إضافة طالب
			break;
		case 2:
			// البحث عن طالب
			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. اقتراحات توسيع المشروع

(1) 5.1 توسيعات الميزات

الميزة الصعوبة الوصف
إحصائيات الدرجات ⭐⭐ حساب المتوسطات، الترتيب
التحقق من البيانات ⭐⭐ التحقق من صحة الإدخال
معالجة الاستثناءات ⭐⭐⭐ استخدام try-catch للأخطاء
واجهة رسومية ⭐⭐⭐⭐ استخدام Qt أو wxWidgets
قاعدة بيانات ⭐⭐⭐⭐ استخدام SQLite أو MySQL

(2) 5.2 تحسين الكود

التحسين الوصف
المؤشرات الذكية استخدام unique_ptr لإدارة الذاكرة
صحة الثوابت استخدام const حيثما أمكن
معالجة الاستثناءات استخدام try-catch لأخطاء الملفات
التحميل الزائد للعوامل تحميل زائد << للخرج

▶ مثال 3: تسلسل وراثة أصناف بسيط (الصعوبة ⭐)

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;
}
▶ جرّب الكود

الخرج:

TEXT 📖 للعرض فقط
: Woof!
: Meow!

❓ أسئلة شائعة

س: لماذا نستخدم مؤشرات لتخزين الطلاب؟ ج: لتحقيق تعدد الأشكال. استخدام vector<Student> سيسبب تقطيع الكائنات، لذا يمكن فقط استدعاء دوال الصنف الأساسي.


س: ماذا عن تسرب الذاكرة؟ ج: استخدم المؤشرات الذكية (unique_ptr) لإدارة الذاكرة تلقائيًا — لا حاجة لـ delete يدوي.


س: كيف يجب أن أصمم تنسيق الملف؟ ج: يمكنك استخدام: - تنسيق CSV: بسيط، لكن وظائف محدودة - تنسيق JSON: قوي، يحتاج مكتبة خارجية - تنسيق ثنائي: فعال، لكن غير قابل للقراءة البشرية


س كيف أتعامل مع الأحرف الصينية؟
ج دعم C++ للصينية محدود. اقتراحات: - استخدم wstring + wcout - أو استخدم مكتبة خارجية (مثلاً iconv) - أو خزّن البينيين/الإنجليزية فقط

📖 ملخص

نقطة المعرفة الاستنتاج الرئيسي
تصميم الأصناف صنف أساسي + صنف مشتق، يعكس الوراثة
تعدد الأشكال استخدام مؤشرات/مراجع لاستدعاء دوال افتراضية
عمليات الملفات ofstream للكتابة، ifstream للقراءة
إدارة الذاكرة المدمر يحرر الذاكرة (أو استخدم المؤشرات الذكية)
واجهة القائمة do-while + switch

اقتراحات الدراسة:


📝 تمارين

  1. أساسي (الصعوبة ⭐): عرّف صنف كتاب (عنوان، مؤلف، سعر)، أنشئ 3 كائنات وأخرج خصائصها.

  2. متوسط (الصعوبة ⭐⭐): نفذ تسلسلًا وراثيًا: Shape (صنف أساسي، دالة افتراضية نقية area()) → صنفين مشتقين Circle وRectangle. استدعِ area() بتعدد الأشكال.

  3. متقدم (الصعوبة ⭐⭐⭐): نفذ "نمط المراقب": صنف Subject يحتفظ بقائمة Observer، Observer صنف أساسي مجرد. عند تغير حالة Subject، أبلغ جميع المراقبين.



اكتملت المرحلة 5! التالي: المرحلة 6 (STL المتقدم)

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%