الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

سؤال حول الـ header file

بدأه khaled_prg في 23 أكتوبر 2010 · 21 رد · 6,507 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

سمعت بعض الإخوة يقول أنه لكتابة مشروع ما يجب عليك أن تكتب الدوال على شكل definition في ملف امتداده .h ثم تكتب الدوال على شكل proto type في ملف امتداده .cpp ثم تنشأ ملف آخر بنفس الإمتداد و سيحوي هذا الملف السورس كود و عادة ما يطلق عليه اسم Main.cpp

سؤالي هو :

  • أيهما أفضل !؟
    الطريقة السابقة أم جعل ملف واحد للسورس كود + ملف للمكتبة (يحتوي على definition فقط !)
  • إذا افترضنا أن الطريقة الأولى أفضل فكيف ستتم ترجمة الملف ذو الإمتداد .cpp (الذي يحتوي على دوال من شكل proto type)

بانتظاركم يا إخوة :)

#2

الـ .h تفيد في تقسيم الملفآت

فـ يقلل الوقت بتوزيع المهام .. وكذلك اكتشاف الاخطآء

بحيث نضع الـ declaration فيها

والـ Implementation في ملف الـ cpp

مع اضافه

#include "NameOfProject.h"

في ملف الـ cpp

فأنت عندما تـريد ترجمتها فأنت تترجم ملف الـ cpp وهو يستدعي الـ h

1
#3
اقتباس
الـ .h تفيد في تقسيم الملفآت

فـ يقلل الوقت بتوزيع المهام .. وكذلك اكتشاف الاخطآء

بحيث نضع الـ declaration فيها

والـ Implementation في ملف الـ cpp

مع اضافه

#include "NameOfProject.h"

في ملف الـ cpp

فأنت عندما تـريد ترجمتها فأنت تترجم ملف الـ cpp وهو يستدعي الـ h

لعلك لم تفهم قصدي ! :blush:

أعرف جيدا كيفية إنشاء مكتبات و كتابة دوال بداخلها و سبق أن كتبت عشرات المكتبات في عدة مشاريع صغيرة :) لكنني أسأل :

  • أيهما أفضل !؟
    أن تكتب الدوال على شكل definition في ملف امتداده .h ثم تكتب الدوال على شكل proto type في ملف امتداده .cpp ثم تنشأ ملف آخر (بنفس الإمتداد ) يحتوي على السورس كود و ( عادة ما يطلق عليه اسم Main.cpp) أم جعل ملف واحد للسورس كود + ملف للمكتبة (يحتوي على definition !)
  • إذا افترضنا أن الطريقة الأولى أفضل فـــكيف ستتم ترجمة الملف ذو الإمتداد .cpp (الذي يحتوي على دوال من شكل proto type)

الطريقة التي كنت أعرفها هي إنشاء ملف الـ .h يحتوي على الدوال "كاملة" ثم يتم استدعاء الدوال في ملف الـ .cpp و لكنني قرأت في بعض الكتب أنه لكتابة مشروع بالشكل "القياسي" فيجب أن أنشأ ثلاث ملفات !, أحدها هو الـ .h (و يحتوي على proto type فقط ! ) و الآخر هو .cpp (يحتوي على definition فقط !) و الأخير هو الذي يحتوي على السورس كود.

أتمنى أن تكون الأسئلة قد اتضحت و تكون الإجابة أكثر دقة.

ملاحظة : المشروع من النوع المفتوح المصدر (ليس هناك احتكار لدوال المكتبة حتى أضطر إلى إبعادها عن الـ .h :happy: )

بالتوفيق.

#5

/*قبل البدء الكود و المخطط مقتبس من www.learncpp.com*/

سأضع لك مخطط يشرح لك طريقة العمل عند تقسيم البرنامج (تعريف الدوال في ملف رأسي header file و تعريفهم في ملف cpp)

الحالة الأولى (حالة وجود المكتبة iostream فقط دون وجود أي مكتبة خارجية أخرى )

بفرض البرنامج هو التالي :

#include <iostream>
int main()
{
    using namespace std;
    cout << "Hello, world!" << endl;
    return 0;
}

فإن آلية العمل هي التالي :

post-217808-014391900 1288026911_thumb.p

الحالة الثانية (تعريف ملف رأسي خاص بك )

بفرض الكود هو التالي :

#include <iostream>
#include "add.h" // this brings in the declaration for add()

int main()
{
    using namespace std;
    cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
    return 0;
}

add.h

#ifndef ADD_H
#define ADD_H

int add(int x, int y); // function prototype for add.h

#endif

add.cpp

int add(int x, int y)
{
    return x + y;
}

فإن آلية العمل هي التالي :

post-217808-070668400 1288026900_thumb.p

إذا لم يكن السابق جواباً لـ

اقتباس
إذا افترضنا أن الطريقة الأولى أفضل فـــكيف ستتم ترجمة الملف ذو الإمتداد .cpp (الذي يحتوي على دوال من شكل proto type)

فعندها أقول لك أنها لا تترجم بشكل مستقل فهي رهن إشارة البرنامج الرئيسي main.cpp لحين استدعاءها من المكتبة التابع لها المُتضمنة داخل الـmain

المرفقات
IncludeHeader.pngIncludeLibrary.png
#6

أحس أن الشرح أعلى مما أستطيع استيعابه (أنا لسه مبتدأ كم يوم !) :blush:

يا ريت لو يكون الشرح بالعربية و بدون مخططات لو سمحت !, لأنها تصيبني بالدوار :blink: :wacko:

احترامي لك :)

تم تعديل هذه المشاركة بواسطة khaled_prg في 25 أكتوبر 2010 في 21:30

#8

ساشرحلك بالنسبة لبرامج السى (وهى قريبة غالبا من السى++)

برامج السى تقسم اساسا الى ملفات .c وتلك الملفات تترجم كل واحدة على حدة .

لماذا ال.h ؟

لان كل ملف .c عندما يترجم يتحول الى كيان منفصل فى الذاكرة (module ) عند يتم تحميل البرنامح . وقد يكون احد modules الاخرى تريد استدعاء دوال منها او انشاء متغيرات من data type معرفة فى الmodule الاخرى او استدعاء دوال من تلك الmodule .فهذا لا ينجح .

لماذا لا ينجح ؟

لان الmodule لا تعرف تكوين الdata type المعرفة فى الmodule الاخرى .وبالنسبة للدوال لا تعرف عنها arguments type او return type واذا لم تقدم تلك المعلومات فسيفترضهم عشوائيا .

الحل ؟

فصل تلك المعلومات (الdata type + توقيع الدوال function declaration ) فى ملف منفصل يسمى .h .

كيف يتم معالجة ال

#include "ddd.h"

؟

عندما تكتب هذا السطر يقوم ال preprocessor الذى هو جزء من المترجم بتضمين محتويات ملف ال.h مكان هذا السطر . فبعد ذلك يمكن انشاء متغيرات من تلك الdata type ومعرفة متطلبات الدوال قبل استدعائها فتمكن ملف ال.c من استخدام تلك الدوال و انواع البيانات . لذلك تقوم بتضمين ال.h الخاص باحد الmodules اذا اردت ان تستخدم تلك الmodule .

name : mohamedyosry

#10

من الأفضل كتابة ال prototypes في ال headers وعمل ال implementation في ملف source.

هذه الطريقة لها عدة مميزات.

1- تمكن من عزل ال prototypes عن ال implementation وبالتالي سيكون ملف ال source واضح و غير ممتلئ كذلك بالنسبة لملف ال header .

2- سهولة تتبع الاخطاء و تحديدها : سواء كانت في ال prototypes او في ال implementation.

3- في حالة اردت مثلا ان يتم استعمال "مجموعة من الدوال" داخل عدة ملفات source فما عليك سوى عمل include لملف ال prototypes لهذه الدوال داخل كل ملف سورس. دون الحاجة الى اعادة كل من ال prototypes+implementation داخل كل ملف سورس.

4- ملفات الهيدر ستسهل عليك التعامل مع الدوال inline. تعريف دالة inline داخل ملف هيدر و استعمالها في اي ملف سورس تريد.

الخ...

#11

1 - اصنع ملف بالإمتداد h وضع داخله الـ prototype الخاص بدوالك.

2 - اصنع ملف بالإمتداد cpp ثم قم بداخله بعمل include للملف ذو الإمتداد h الذى تم إنشائه بالخطوه 1 ثم قم بعمل تضمين للداله المعرفه بالملف ذو الإمتداد h داخل الملف ذو الإمتداد cpp.

3 - فى أى وقت داخل مشروعك قم بعمل include للملف ذو الإمتداد h و استخدم التعريفات التى بداخله كما يحلو لك و سيعرف المترجم كيف يحصل على الكود الخاص بتعريف الدوال.

و الله ولي التوفيق

1

مدونتي: C++ Tips and Tricks

#13

انظروا معي إلى التالي :

ملف cout.h

void Cout()
{
cout<<"arabteam2000"<<endl;
}

ملف main.cpp :

#include<cout.h>
#include<iostream>
using namespace std;
int main()
{
Cout();
return 0;
}

هل هذا ما تقصدون !؟

#14

// Fichier test.h
#ifndef TEST_H
#define TEST_H
void cout(void);
#endif


//Fichier test.cpp
#include <iostream>
#include "test.h"
int main()
{
cout();

return 0;
}
void cout(void)
{
std::cout<<"abcdefgh"<<std::endl;
}

بالنسبة لملفات الهيدر

تم تعديل هذه المشاركة بواسطة xpero في 31 أكتوبر 2010 في 02:08

#16

khaled_prg

بالنسبة لوضع ال prototypes في ملفات الهيدر و ال implementation في ملفات السورس فهي طريقة لتنظيم الكود و تسهيل عملية الصيانة.

لا تظهر أهمية هذه الطريقة في مشاريع صغير لا تتعدى بضع اسطر لكن بالنسبة للمشاريع الكبيرة التي تتعدى ملايين الاسطر من الكود فيجب تفريق ال implementation عن ال prototypes , يمكن الاطلاع على ملف هيدر و ستأخذ نظرة واضحة عن ال implementation : برامترات الدوال ....الخ دون الحاجة الى فتح ملف السورس الضخم و البحث عن دالة معينة داخل عدة ملايين الاسطر من الكود.

#17

طريقة دمج ال implementation و الـ prototype في ملف .h هي التي اعتمد عليها الأستاذ وجدي عصام في مشروعه Computer Viruses strategies and detection techniques و الذي يحتوي على آلاف الأسطر البرمجية, كيف ترد !؟

البعض يفضل هذه الطريقة (و التي لم أفهمها بعد !):

أن تكتب الدوال على شكل definition في ملف امتداده .h ثم تكتب الدوال على شكل proto type في ملف امتداده .cpp ثم تنشأ ملف آخر بنفس الإمتداد و سيحوي هذا الملف السورس كود و عادة ما يطلق عليه اسم Main.cpp

ما رأيك !؟

تم تعديل هذه المشاركة بواسطة khaled_prg في 31 أكتوبر 2010 في 14:28

#18

khaled_prg

لا تهتم لما يفعله هذا الشخص او ذاك اخي :)

القواعد القياسية تنوه بوضع ال declarations td في الهيدرات و ال implementation في ملفات السورس.

مكتبات السي++ كلها تستخدم هذه الطريقة.

مطور لغة السي++ bjarne stroustrup ينوه بهذه الطريقة و ينصح بعدم استعمال طريقة وجدي عصام + الطريقة الثانية.

تم تعديل هذه المشاركة بواسطة xpero في 31 أكتوبر 2010 في 14:55

#19
اقتباس
مطور لغة السي++ bjarne stroustrup ينوه بهذه الطريقة و ينصح بعدم استعمال طريقة وجدي عصام + الطريقة الثانية.

كلام خطير يا أخي !, أظنك تعرف الأستاذ وجدي عصام جيدا :cool: + كيف تخفى عليه مثل هذه الأشياء إن كانت غير محببة !؟ :wink:

ما دليلك !؟, أريد كلام البروفيسور bjarne stroustrup نفسه :happy:

أشكرك على متابعة الموضوع, دعائي بظهر الغيب لك :wub:

#20
khaled_prg كتب:

كلام خطير يا أخي !, أظنك تعرف الأستاذ وجدي عصام جيدا :cool: + كيف تخفى عليه مثل هذه الأشياء إن كانت غير محببة !؟ :wink:

ما دليلك !؟, أريد كلام البروفيسور bjarne stroustrup نفسه :happy:

أشكرك على متابعة الموضوع, دعائي بظهر الغيب لك :wub:

هذا مقتطف من كتاب the C++ programming language ل bjarne stroustrup الجزء 9.5 (الصفحة 231 في ملف ال pdf)

cppn.jpg

#21

اظن ان كتاب the C++ programming language هو أفضل كتاب على الاطلاق لتعلم سي++ او بالاحرى standard C++ بالنحو الصحيح.

هل تعرف scott Meyers ؟ هو من أفضل مبرمجي C++ في العالم !!! ورشح كتاب The C++ programming language كأول أهم كتاب في C++. لانه بكل بساطة مؤلفه هو مطور اللغة نفسها.

#22
اقتباس
اظن ان كتاب the C++ programming language هو أفضل كتاب على الاطلاق لتعلم سي++ او بالاحرى standard C++ بالنحو الصحيح.

بكل تأكيد :)

اقتباس
هل تعرف scott Meyers ؟

هل يمكن أن يسجل في المنتدى و يعرفنا بنفسه !؟ :P

اقتباس
رشح كتاب The C++ programming language كأول أهم كتاب في C++. لانه بكل بساطة مؤلفه هو مطور اللغة نفسها.

لا داعي لذلك !, فالعين لا تعلو على الحاجب :happy:, مادام الكتاب لصاحب اللغة فلا نحتاج لمن يرشحه كأفضل كتاب ! :)

==============

الأخ xpero كلامه وضاح و لا غبار عليه و قد قدم دليله الدامغ :cool: , إذا كان هناك من يعارضه من الأعضاء فليتقدم إلى منصة النقاش :wink:

تم تعديل هذه المشاركة بواسطة khaled_prg في 31 أكتوبر 2010 في 18:07

مواضيع مشابهة