C++: أساسيات الفئات والكائنات
آخر تحديث: 2026-08-26
في الدروس السابقة، استخدمنا البنى لجمع متغيرات من أنواع مختلفة في وحدة واحدة.
لكن الأشياء في العالم الحقيقي لها خصائص (مثل الاسم، العمر) وأيضاً سلوكيات (مثل المشي، التحدث).
تُستخدم الفئات لوصف "الأشياء" — فهي تُغلّف الخصائص والسلوكيات معاً.
1. ما هي الفئة؟
(1) 1.1 الفئات في الحياة اليومية
| مثال من الحياة اليومية | المكافئ البرمجي |
|---|---|
| مخطط معماري (يصف هيكل المنزل) | فئة (قالب يصف الأشياء) |
| منزل مبني من المخطط (الكائن الفعلي) | كائن (نسخة من فئة) |
الفئة مقابل الكائن:
- الفئة هي قالب (تصف الخصائص والسلوكيات التي يجب أن يمتلكها "الطالب")
- الكائن هو نسخة (شيء ملموس يُنشأ من القالب — الطالب "Zhang San")
(2) 1.2 لماذا نحتاج الفئات؟
بدون الفئات (باستخدام البنى، مع قيود):
#include <iostream>
#include <string>
struct Student {
std::string name;
int age;
double score;
};
int main() {
Student s1 = {"Alice", 20, 92.5};
// ❌ البنى لا يمكنها تضمين "السلوكيات" (مثل "قدّم نفسك")
return 0;
}
مع الفئات (كامل):
#include <iostream>
#include <string>
class Student {
public:
std::string name;
int age;
double score;
void introduce() {
std::cout << "My name is " << name << ",this year " << age << " years old。" << std::endl;
}
};
int main() {
Student s1;
s1.name = "Alice";
s1.age = 20;
s1.introduce(); // ✅ الفئات يمكنها تضمين "السلوكيات"
return 0;
}
2. تعريف الفئة*
(1) 2.1 الصياغة الأساسية
class ClassName {
public:
// الأعضاء (الخصائص والسلوكيات)
};
💡 نقطة مهمة: ينتهي تعريف الفئة بـ فاصلة منقوطة! (مثل البنى)
▶ مثال 1: تعريف فئة طالب (الصعوبة ⭐)
#include <iostream>
#include <string>
class Student {
public:
// خصائص (متغيرات الأعضاء)
std::string name;
int age;
double score;
// سلوكيات (دوال الأعضاء)
void introduce() {
std::cout << "My name is " << name << ",this year " << age << " years old。" << std::endl;
}
void study() {
std::cout << name << " is studying..." << std::endl;
}
};
int main() {
Student s1;
s1.name = "Alice";
s1.age = 20;
s1.score = 92.5;
s1.introduce();
s1.study();
return 0;
}
الخرج:
My name is Alice,this year 20 years old。
Alice is studying...
3. التحكم في الوصول*
تحتوي فئات C++ على ثلاث مستويات وصول: public وprivate وprotected.
(1) 3.1 public مقابل private*
| مستوى الوصول | يمكن الوصول إليه خارج الفئة؟ | الغرض |
|---|---|---|
| public | ✅ نعم | الواجهة العامة (للاستخدام الخارجي) |
| private | ❌ لا | التنفيذ الداخلي (إخفاء التفاصيل) |
مثال:
#include <iostream>
#include <string>
class Student {
private:
std::string name; // عضو خاص
int age;
public:
//.Setter و getter عامان
void setName(const std::string& n) {
name = n;
}
std::string getName() {
return name;
}
};
int main() {
Student s1;
// s1.name = "Alice"; // خطأ: name خاص
s1.setName("Alice"); // صحيح: الوصول عبر دالة عامة
std::cout << s1.getName() << std::endl;
return 0;
}
💡 مبدأ التغليف: اجعل الخصائص private، وادخلها عبر دوال setter/getter العامة — هذا يتيح لك التحكم في منطق الوصول (مثلاً: التحقق مما إذا كان العمر سالباً).
4. البانيات*
(1) 4.1 ما هو الباني؟
الباني هو دالة خاصة في فئة — يُستدعى تلقائياً عند إنشاء كائن.
| الخاصية | الوصف |
|---|---|
| الاسم | نفس اسم الفئة |
| لا قيمة إرجاع | ولا حتى void |
| يُستدعى تلقائياً | يُنفَّذ عند إنشاء كائن |
▶ مثال 2: تعريف باني (الصعوبة ⭐⭐)
#include <iostream>
#include <string>
class Student {
private:
std::string name;
int age;
public:
// باني
Student(const std::string& n, int a) {
name = n;
age = a;
std::cout << "Student Object created: " << name << std::endl;
}
void introduce() {
std::cout << "My name is " << name << ",this year " << age << " years old。" << std::endl;
}
};
int main() {
Student s1("Alice", 20); // صحيح: يُستدعى الباني تلقائياً عند إنشاء الكائن
s1.introduce();
return 0;
}
الخرج:
Student Object created: Alice
My name is Alice,this year 20 years old。
5. المدمرات*
(1) 5.1 ما هو المدمر؟
المدمر هو دالة خاصة أخرى في فئة — يُستدعى تلقائياً عند تدمير كائن (مثلاً عند انتهاء دالة، أو عند استدعاء delete).
| الخاصية | الوصف |
|---|---|
| الاسم | ~ClassName |
| لا قيمة إرجاع | ولا حتى void |
| لا معاملات | لا يمكنه قبول معاملات |
| يُستدعى تلقائياً | يُنفَّذ عند تدمير كائن |
▶ مثال 3: تعريف مدمر (الصعوبة ⭐⭐)
#include <iostream>
#include <string>
class Student {
private:
std::string name;
public:
// باني
Student(const std::string& n) {
name = n;
std::cout << "Constructor: " << name << " created" << std::endl;
}
// مدمر
~Student() {
std::cout << "Destructor: " << name << " destroyed" << std::endl;
}
};
int main() {
Student s1("Alice"); // استدعاء الباني
// عند انتهاء main()، يُدمر s1، ويُستدعى المدمر
return 0;
}
الخرج:
Constructor: Alice created
Destructor: Alice destroyed
💡 الاستخدام: حرّر الموارد في المدمر (مثلاً: إغلاق الملفات، تحرير الذاكرة الديناميكية).
6. المؤشر this*
(1) 6.1 ما هو المؤشر this؟
this هو مؤشر يشير إلى الكائن الحالي — داخل دالة عضو، يمكن استخدام this للوصول إلى الكائن الحالي.
▶ مثال 4: استخدام this للتمييز بين المعاملات التي تحمل نفس الاسم (الصعوبة ⭐⭐)
#include <iostream>
#include <string>
class Student {
private:
std::string name;
public:
void setName(const std::string& name) { // تحذير: اسم المعامل نفس اسم متغير العضو
this->name = name; // صحيح: استخدم this-> للوصول إلى متغير العضو
}
std::string getName() {
return this->name; // صحيح: يمكن حذف this-> (يُنصح بحذفه)
}
};
int main() {
Student s1;
s1.setName("Alice");
std::cout << s1.getName() << std::endl;
return 0;
}
الخرج:
Alice
💡 نصيحة: إذا كان اسم المعامل يختلف عن اسم متغير العضو، فلست بحاجة إلى this-> (يُنصح بحذفه لكود أنظف).
7. تطبيق: فئة حساب بنكي بسيط*
▶ مثال 5: فئة BankAccount (الصعوبة ⭐⭐⭐)
#include <iostream>
#include <string>
#include <iomanip>
class BankAccount {
private:
std::string owner;
double balance;
public:
// باني
BankAccount(const std::string& o, double initialBalance) {
owner = o;
if (initialBalance >= 0) {
balance = initialBalance;
} else {
balance = 0.0;
std::cout << "⚠️ Initial balance cannot be negative, set to 0" << std::endl;
}
}
// إيداع
void deposit(double amount) {
if (amount > 0) {
balance += amount;
std::cout << "Deposit successful! +" << amount << std::endl;
} else {
std::cout << "⚠️ Deposit amount must be greater than 0" << std::endl;
}
}
// سحب
void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
std::cout << "Withdrawal successful! -" << amount << std::endl;
} else if (amount <= 0) {
std::cout << "⚠️ Withdrawal amount must be greater than 0" << std::endl;
} else {
std::cout << "⚠️ Insufficient balance" << std::endl;
}
}
// استعلام الرصيد
void queryBalance() {
std::cout << std::fixed << std::setprecision(2);
std::cout << "Account balance: " << balance << " yuan" << std::endl;
}
};
int main() {
BankAccount account("MOTO", 1000.0);
account.queryBalance();
account.deposit(500.0);
account.queryBalance();
account.withdraw(200.0);
account.queryBalance();
account.withdraw(2000.0); // رصيد غير كافٍ
return 0;
}
الخرج:
Account balance: 1000.00 yuan
Deposit successful! +500.00
Account balance: 1500.00 yuan
Withdrawal successful! -200.00
Account balance: 1300.00 yuan
⚠️ Insufficient balance
نتيجة التنفيذ:
Account balance: 1000.00 yuan
Deposit successful! +500.00
Account balance: 1500.00 yuan
Withdrawal successful! -200.00
Account balance: 1300.00 yuan
⚠️ Insufficient balance
❓ أسئلة شائعة
📖 ملخص
- الفئات: تُغلّف البيانات والعمليات معاً
- الكائنات هي نسخ من الفئات، يُدخل إليها عبر . أو ->
- معدِّلات الوصول: public/protected/private
- دوال الأعضاء تُعلن داخل الفئة ويمكن تعريفها داخلها أو خارجها
- البانيات: تُستدعى تلقائياً عند إنشاء كائن، تُستخدم للتهيئة
📝 تمارين
-
أساسي (الصعوبة ⭐): عرّف فئة
Bookبثلاثة أعضاء خاصين: العنوان، المؤلف، والسعر. -
وفّر دوال setter و getter عامة
-
أنشئ كائنين
Bookفيmainوأخرج معلوماتهما -
متوسط (الصعوبة ⭐⭐): عرّف فئة
Rectangleبعضوين خاصين: العرض والارتفاع. -
وفّر بانيًا بمعاملات
-
وفّر دوال أعضاء
double getArea()وdouble getPerimeter() -
اختبر في
main -
متقدم (الصعوبة ⭐⭐⭐): عرّف فئة
Dateبثلاثة أعضاء خاصين: السنة، الشهر، واليوم. -
وفّر بانيًا بمعاملات
-
وفّر دالة عضو
bool isValid()(تتحقق من صحة التاريخ) -
وفّر دالة عضو
void print()(تُخرج التاريخ بالصيغة:2024-02-29) -
اختبر في
main
8. 🚀 الخطوات التالية*
الآن بعد أن تعلمت أساسيات الفئات والكائنات، لننتقل إلى البانيات المتقدمة (الدرس 29) — البانيات الافتراضية، بانيات النسخ، ودلالات النقل (ميزة C++11)!