Mohssen A Mohssen نشر 21 نوفمبر 2021 أرسل تقرير مشاركة نشر 21 نوفمبر 2021 أحاول أن أقوم بعمل ملفين header وأحد هذه الملفات معتمد على الآخر: الملف الأول square.h: int getSquareSides() { return 4; // مجرد كود بسيط } الملف الثاني geometry.h يعتمد على الملف الأول ويقوم بتضمينه كالتالي: #include "square.h" ملف main.cpp: #include "square.h" #include "geometry.h" int main() { // ... return 0; } عندما أقوم بتضمين كلا الملفين يظهر لي الخطأ التالي في ملف square.h: Error C2084 function 'int getSquareSides(void)' already has a body ما سبب هذا الخطأ؟ وكيف أقوم بتضمين ملف ترويسة header أكثر من مرة بدون ظهور هذا الخطأ؟ 1 اقتباس رابط هذا التعليق شارك على الشبكات الإجتماعية More sharing options...
2 سامح أشرف نشر 21 نوفمبر 2021 أرسل تقرير مشاركة نشر 21 نوفمبر 2021 يظهر هذا الخطأ بسبب تعريف الدالة getSquareSides أكثر من مرة (مرة لكل تضمين include) وبالتالي لا يستطيع المترجم التفريق بين الدوال التي لها نفس التوقيع signature (نوع الرجوع return type + اسم الدالة + المعاملات التي تقبلها الدالة)، وهنا ما يقوم به المصرف compiler بشكل مفصل: أولًا يقوم المصرف بتضمين الملف square.h في الملف main.cpp، وبالتالي يتم نسخ الدالة getSquareSides إلى الملف main.cpp لأول مرة بعد ذلك يتم تضمين الملف geometry.h في الملف main.cpp، والذي بدورة يقوم بتضمين الملف square.h مرة أخرى، وبهذا يتم نسخ محتوى الملف square.h إلى داخل geometry.h ثم نسخ محتوى الملف geometry.h (بما في ذلك الدالة getSquareSides) إلى الملف main.cpp وسيكون شكل الكود في النهاية (بالنسبة للمصرف compiler)، كالتالي: int getSquareSides() // من الملف square.h { return 4; } int getSquareSides() // من الملف geometry.h (عبر square.h) { return 4; } int main() { return 0; } كل ملف على حدى لا يحتوي على أخطاء ولكن إستدعاء هذه الملفات بشكل هرمي ومتوازي معًا يسبب خطأ تعريف نفس الدالة لأكثر من مرة. لحل هذه المشكلة يجب إستخدام Header guards أو ما يسمى بواقيات معالج مسبق (Preprocessor Guards)، كالتالي: الملف square.h: #ifndef SQUARE_H #define SQUARE_H // لن يتم تضمين الدالة التالية إلا مرة واحدة فقط int getSquareSides() { return 4; } #endif الملف geometry.h: #ifndef GEOMETRY_H #define GEOMETRY_H #include "square.h" #endif ويبقى الملف main.cpp كما هو بدون تغير، وبالتالي سيكون شكل الملف main.cpp بعد عملية preprocessing على الشكل التالي: // تضمين الملف square.h من داخل main.cpp #ifndef SQUARE_H #define SQUARE_H int getSquareSides() { return 4; } #endif // SQUARE_H // تضمين الملف geometry.h من داخل main.cpp #ifndef GEOMETRY_H #define GEOMETRY_H #ifndef SQUARE_H // تضمين الملف square.h من داخل geometry.cpp , SQUARE_H معرفة بالفعل في الأعلى #define SQUARE_H // لذلك لن يتم تضمين هذا المحتوى مرة أخرى في عملية التصريف compiling int getSquareSides() { return 4; } #endif // SQUARE_H #endif // GEOMETRY_H int main() { // ... return 0; } يمكنك أن تقرأ أكثر حول الـ Header guards من خلال هذه المقالة هنا، حيث يتم شرح كيفية تضمين ملفات الترويسة Headers بطيرقة صحيحة: 3 اقتباس رابط هذا التعليق شارك على الشبكات الإجتماعية More sharing options...
السؤال
Mohssen A Mohssen
أحاول أن أقوم بعمل ملفين header وأحد هذه الملفات معتمد على الآخر:
الملف الأول square.h:
الملف الثاني geometry.h يعتمد على الملف الأول ويقوم بتضمينه كالتالي:
ملف main.cpp:
عندما أقوم بتضمين كلا الملفين يظهر لي الخطأ التالي في ملف square.h:
ما سبب هذا الخطأ؟ وكيف أقوم بتضمين ملف ترويسة header أكثر من مرة بدون ظهور هذا الخطأ؟
رابط هذا التعليق
شارك على الشبكات الإجتماعية
1 جواب على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.