C++ تضمين الملفات

ملفات المشروع

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

سابقاً كنا نكتب كل كود المشروع بداخل ملف واحد بهدف جعلك تركز على المفاهيم الجديدة التي كنا نشرحها في كل درس.
في هذا الدرس ستتعلم كيف تقوم بتوزيع كود المشروع على عدة ملفات و من ثم كيف تتعامل معها و كأنها موجودة كلها في نفس الملف.


تضمين كود ملف في ملف

في حال أردت تضمين الكود الموجود في ملف إمتداده .cpp في ملف آخر إمتداده .cpp فيوجد طريقتين لذلك:

  • تضمين كل شيء تريد استخدامه من الملف على حدا و هذا الأسلوب لا يتم اتباعه في العادة لأنه متعب.
  • تضمين كل محتوى الملف دفعة واحدة و استخدام ما تريده منه بشكل مباشر و هذا الأسلوب الأفضل لذلك.

ستتعلم لاحقاً من الأمثلة كيفية تطبيق كلا الطريقتين و لكن تذكر أن الطريقة الثانية هي الأفضل لذلك لأنها توفر عليك الكثير من الوقت و التكرار.


ملاحظة

سنقوم بشرح كيفية إنشاء ملفات بواسطة برنامج CodeBlocks لأنه البرنامج الذي نستخدمه في هذه الدورة و لكن عليك معرفة أن منطق إنشاء الملفات و تضمين محتواها هو نفسه تماماً في أي برنامج آخر.


تضمين ما يلزم فقط

في الأمثلة التي وضعناها في هذا الدرس ستلاحظ أننا لم نكتب الأمر using namespace std; كما كنا نفعل في السابق و سبب ذلك أننا سنبدأ بمحاولة تضمين ما نحتاج تضمينه فقط من الكود.

إذاً حين تجد أننا كتبنا std::cout و std::endl فنحن بذلك نستخدم cout و endl و لكن بدون تضمين كل ما هو موجود في المكتبة std.

تحديد الكود الذي سيتم تضمينه من الملف

في حال أردت تضمين متغير, دالة, كلاس إلخ.. موجود في ملف ما بداخل ملف آخر يجب أن تعيد ذكر تعريف ( Declaration ) ذاك الشيء في الملف الذي تنوي استخدامه فيه لأنك بهذا الأسلوب تعلم المترجم بأن ما تستخدمه هو شيء موجود في المشروع, و بالتالي فإنه عند التشغيل يقوم هو بالبحث عن المكان الذي تم فيه تعريف هذا الشيء.


في المثال التالي قمنا بإنشاء ملف جديد في المشروع إسمه demo.cpp.
في حال كنت لا تعرف كيف تنشئ الملف بنفسك, قم باتباع الخطوات الموضوعة هنا لتنشئه.

خطوات إنشاء الملف »


الصورة التالية تظهر الشكل العام لمجلدات و ملفات المشروع.


الآن سنقوم بتعريف ثلاث دوال بسيطة في الملف demo.cpp.
بعدها سنقوم بتضمين هذه الدوال و استدعائها في الملف main.cpp.

مثال

demo.cpp
#include <iostream>

// هنا قمنا بتعريف دالة تقوم بطباعة جملة ترحيب عند استدعائها
void greetings()
{
	std::cout << "Welcome to harmash.com" << std::endl;
}

// هنا قمنا بتعريف دالة تقوم بطباعة الأرقام الموجودة من 1 إلى العدد الذي نمرره لها عند استدعائها
void printFromOneTo(int n)
{
	for (int i=1; i<=n; i++)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
}

// هنا قمنا بتعريف دالة نمرر لها ثلاث أعداد عند استدعائها فترجع لنا ناتج جمعهم
int sum(int a, int b, int c)
{
	return a + b + c;
}
		

main.cpp
#include <iostream>

// حتى يتم تضمينهم في هذا الملف و بالتالي لنتمكن من استدعائهم demo.cpp للدوال الثلاثة الموجودة في الملف (Header) هنا قمنا بذكر الشكل العام
void greetings();
void printFromOneTo(int n);
int sum(int a, int b, int c);

int main()
{
	// greetings() هنا قمنا باستدعاء الدالة
	greetings();
	
	// مع تمرير القيمة 10 لها حتى تطبع جميع الأرقام الموجودة من 1 إلى 10 printFromOneTo() هنا قمنا باستدعاء الدالة
	printFromOneTo(10);
	
	// مع تمرير ثلاث أعداد لها و طباعة ناتج الجمع الذي سترجعه لنا sum() هنا قمنا باستدعاء الدالة
	std::cout << "1 + 2 + 3 = " << sum(1, 2, 3);

	return 0;
}
		

سنحصل على النتيجة التالية عند التشغيل.

Welcome to harmash.com
1 2 3 4 5 6 7 8 9 10
1 + 2 + 3 = 6
		

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

تضمين كل الكود الموجود في الملف دفعة واحدة

في العادة, لجعل كل الكود الموجود في ملف إمتداده .cpp يمكن تضمينه دفعة واحدة يتم إنشاء ملف موازي له يملك نفس الإسم و إمتداده .h و فيه نقوم فقط بذكر الشكل العام ( Declarations ) لما يحتويه الملف الأول فقط.
عندها أي ملف يريد تضمين كل الكود الموجود في الملف الذي إمتداده .cpp يقوم بتضمين الملف .h الموازي له فقط.


مصطلحات تقنية

  • أي ملف إمتداده .cpp يقال له ملف مصدري ( Source File ) و معنى ذلك أنه يحتوي على الكود نفسه.
  • أي ملف إمتداده .h يقال له ملف أساسي ( Header File ) و معنى ذلك أنه يحتوي على الشكل العام أو الأساسي للكود فقط.


الشكل العام لأي ملف أساسي ( Header File )

الملف الذي يكون إمتداده .h يوجد أسلوبين لتعريفه: أسلوب #ifndef القديم أو أسلوب #pragma الحديث.
الفرق الوحيد بينهما هو أن أسلوب #ifndef يتطلب كتابة ثلاث أسطر, أما أسلوب #pragma once فيتطلب كتابة سطر واحد فقط.


الشكل العام لملف إمتداده .h بأسلوب #ifndef.

#ifndef FILE_NAME       // تضع أي إسم لم تقم باستخدامه من قبل FILE_NAME مكان الكلمة
#define FILE_NAME       // تضع أي إسم لم تقم باستخدامه من قبل FILE_NAME مكان الكلمة

// و الذي تريد تضمينه في ملف آخر cpp هنا تضع الشكل العام لأي شيء موجود في الملف

#endif
	

الشكل العام لملف إمتداده .h بأسلوب #pragma once.

#pragma once

// و الذي تريد تضمينه في ملف آخر cpp هنا تضع الشكل العام لأي شيء موجود في الملف
	


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



ملاحظة

عند إنشاء ملف إمتداده .h بواسطة برنامج CodeBlocks نلاحظ أنه يعتمد الأسلوب القديم #ifndef حيث تجده يكتب عنك بشكل تلقائي الأسطر الثلاثة الخاصة بهذا الأسلوب بمجرد إنشاء الملف. طبعاً يمكنك مسحها و كتابة #pragma once بنفسك إن أردت أو إبقاء الأسلوب.



في المثال التالي قمنا بإنشاء ملف جديد في المشروع إسمه demo.h وضعنا فيه الشكل العام لما يحتويه الملف demo.cpp الذي أنشأناه سابقاً.
في حال كنت لا تعرف كيف تنشئ الملف بنفسك, قم باتباع الخطوات الموضوعة هنا لتنشئه.

خطوات إنشاء الملف »


الصورة التالية تظهر الشكل العام لمجلدات و ملفات المشروع.


الآن سنقوم بتعريف شكل الدوال الموجودة في الملف demo.cpp في الملف demo.h.
بعدها سنقوم بتضمين الملف demo.h في الملف main.cpp و من ثم استدعاء الدوال الموجودة في الملف demo.cpp تماماً كما فعلنا في المثال السابق.

مثال

demo.cpp
#include <iostream>

// هنا قمنا بتعريف دالة تقوم بطباعة جملة ترحيب عند استدعائها
void greetings()
{
	std::cout << "Welcome to harmash.com" << std::endl;
}

// هنا قمنا بتعريف دالة تقوم بطباعة الأرقام الموجودة من 1 إلى العدد الذي نمرره لها عند استدعائها
void printFromOneTo(int n)
{
	for (int i=1; i<=n; i++)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
}

// هنا قمنا بتعريف دالة نمرر لها ثلاث أعداد عند استدعائها فترجع لنا ناتج جمعهم
int sum(int a, int b, int c)
{
	return a + b + c;
}
		

demo.h
#pragma once

// فقط يقوم بتضمين كل هذه الدوال demo.h الأمر الذي سيجعل تضمين الملف demo.cpp للدوال الثلاثة الموجودة في الملف (Header) هنا قمنا بذكر الشكل العام
void greetings();
void printFromOneTo(int n);
int sum(int a, int b, int c);
		

main.cpp
#include <iostream>
#include "demo.h"       // و بالتالي أصبح بإمكاننا استخدام أي شيء تعريفه مذكور فيه demo.h هنا قمنا بتضمين محتوى الملف

int main()
{
	// greetings() هنا قمنا باستدعاء الدالة
	greetings();
	
	// مع تمرير القيمة 10 لها حتى تطبع جميع الأرقام الموجودة من 1 إلى 10 printFromOneTo() هنا قمنا باستدعاء الدالة
	printFromOneTo(10);
	
	// مع تمرير ثلاث أعداد لها و طباعة ناتج الجمع الذي سترجعه لنا sum() هنا قمنا باستدعاء الدالة
	std::cout << "1 + 2 + 3 = " << sum(1, 2, 3);

	return 0;
}
		

سنحصل على النتيجة التالية عند التشغيل.

Welcome to harmash.com
1 2 3 4 5 6 7 8 9 10
1 + 2 + 3 = 6
		


الطريقة الأسهل في كتابة الكود

من الأفضل دائماً أن تبدأ بذكر الشكل العام للأشياء التي ستقوم بتعريفها بداخل الملف الذي إمتداده .h و من بعدها تقوم بتضمين الملف .h بداخل الملف .cpp لأن هذا الأسلوب سيجعل البرنامج الذي تستخدمه في كتابة الكود يساعدك في إكمال الكود.


الآن سنعيد المثال السابق و لكننا سنبدأ بكتابة الكود في الملف demo.h يليه demo.cpp يليه main.cpp بدون إجراء أي تعديل على الدوال السابقة.
ملاحظة: سنقوم بتضمين demo.h في الملف demo.cpp لجعل المترجم يتعرّف على الدوال الموجودة فيه و بالتالي لجعله قادر على مساعدتنا في إكمال الكود.

مثال

demo.h
#pragma once

// demo.cpp للدوال الثلاثة التي سننشئها في الملف (Header) هنا قمنا بذكر الشكل العام
void greetings();
void printFromOneTo(int n);
int sum(int a, int b, int c);
		

demo.cpp
#include <iostream>
#include "demo.h"          // و بالتالي أصبح المترجم قادر على مساعدتنا في إكمال الكود demo.h هنا قمنا بتضمين محتوى الملف

// ستلاحظ أن البرنامج الذي تستخدمه في كتابة الكود سيساعدك في كتابة الشكل العام لها greetings() أثناء تعريف الدالة
void greetings()
{
	std::cout << "Welcome to harmash.com" << std::endl;
}

// ستلاحظ أن البرنامج الذي تستخدمه في كتابة الكود سيساعدك في كتابة الشكل العام لها printFromOneTo() أثناء تعريف الدالة
void printFromOneTo(int n)
{
	for (int i=1; i<=n; i++)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
}

// ستلاحظ أن البرنامج الذي تستخدمه في كتابة الكود سيساعدك في كتابة الشكل العام لها sum() أثناء تعريف الدالة
int sum(int a, int b, int c)
{
	return a + b + c;
}
		

main.cpp
#include <iostream>
#include "demo.h"       // و بالتالي أصبح بإمكاننا استخدام أي شيء تعريفه مذكور فيه demo.h هنا قمنا بتضمين محتوى الملف

int main()
{
	// سيساعدك المترجم في كتابة إسمها "demo.h" عند استدعاء أي دالة موجودة في الملف
	greetings();
	printFromOneTo(10);
	std::cout << "1 + 2 + 3 = " << sum(1, 2, 3);

	return 0;
}
		

سنحصل على النتيجة التالية عند التشغيل.

Welcome to harmash.com
1 2 3 4 5 6 7 8 9 10
1 + 2 + 3 = 6
		

الفرق بين #include " ... " و #include < ... >

الملفات التي إمتدادها .h و التي تجدها جاهزة في C++ أو التي قمت بإعلام المترجم بنفسك أين يجدها - و هذا الشيء ستتعلمه في الدرس القادم - نقوم بتضمينها بأسلوب #include < ... > و إليك بعض الأمثلة.

#include <iostream>
#include <vector>
#include <queue>
	

الملفات التي إمتدادها .h و التي تكون أنت أو أي مبرمج آخر من أنشائها و لم يتم إعلام المترجم عن مكان وجودها نقوم بتضمينها بأسلوب #include " ... " لأنه يسمح لنا بتحديد مكان وجود هذه الملفات بأنفسنا و إليك بعض الأمثلة.

// موجود مباشرةً بداخل المشروع و ليس موضوع بداخل أي مجلد student.h هذا يعني أن هذا الملف 
#include "student.h"

// school موجود في المشروع بداخل مجلد إسمه student.h هذا يعني أن هذا الملف 
#include "school/student.h"

// D://libraries/school موجود في المسار student.h هذا يعني أن هذا الملف
#include "D://libraries/school/student.h"
	

طريقة حذف ملفات من المشروع في CodeBlocks

إذا أردت حذف الملفين demo.cpp و demo.h اللذين أنشأنهما في الأمثلة السابقة إبتع الخطوات التالية.

1. أنقر على إسم المشروع الذي تريد حذف أو أكثر منه.
2. أنقر على الزر Remove Files... كالتالي.


3. قم بتحديد الملفات التي تريد حذفها و في حالتنا سنحذف الملفين demo.cpp و demo.h.
4. أنقر على الزر OK كالتالي.


5. أنقر على الزر Yes كالتالي.

طريقة إنشاء ملف .cpp و ملف .h له دفعة واحدة في CodeBlocks

بشكل عام, في المشاريع يتم إنشاء كل كلاس بداخل ملف .cpp خاص و يتم إنشاء ملف .h له حتى يتم تضمين محتواه بسهولة من خلاله.
في حال أردت إنشاء كلاس جديد مع إنشاء الملفين .cpp و .h له دفعة واحدة, قم باتباع الخطوات التالية.

1. أنقر على أيقونة إنشاء ملف جديد.

2. أنقر على الزر Class... كالتالي.


3. قم بوضع إسم الكلاس الذي تريد إنشاؤه مكان مربع النص Class name: لتحديدها.
4. أنقر على الزر Create كالتالي.


5. أنقر على الزر Yes كالتالي.


6. أنقر على الزر Select All حتى يتم وضع علامة صح على الخيارين Debug و Release.

7. أنقر على الزر OK كالتالي.


8. إذا اتبعت نفس الخطوات التي ابتعناها سيتم إنشاء الملف Person.cpp في مجلد إسمه src و الملف Person.h في مجلد إسمه include كالتالي.


الكود الذي تجده جاهزاً في أي ملف يتم إنشاؤه في المشروع يمكنك حذفه أو تعديله بالشكل الذي تريده.
حتى أنك تستطيع كما شاهدت سابقاً في الخطوة الثالثة تحديد الكود الذي سيتم تجهيزه لك في هذه الملفات.

الدورات

أدوات مساعدة

أقسام الموقع

دورات
مقالات كتب مشاريع أسئلة