الشبكة العربية لمطوري الألعاب

مبتدئ  Ali Amin مشاركة 1

لدي سؤالين عن لغة السي++ 



أول سؤال ,  اهم فرق بين السي و السي بلس بلس , هي استعمال الكلاسات , فلو كنت تستعمل الكلاسات فأنت تستعمل لغة سي بلس بلس , طب لو كنت استعمل مزيج من الأثنين , بمعنى أكتب دوال عامة من دون كلاسات و استعمل ايضا الكلاسات , فماذا يعتبر هذا ؟ هل البرمجة الصحيحة إني اكون Full oop و لا اكتب اي شىء بخارج كلاسات ؟


مثلا لغة كالسي شارب لا تتيح لك إلا ان تكتب كل شىء بداخل كلاسات 


سؤالي الثاني عن المؤشر ذو البعدين (اعتقد ان اسمه هذا ) مثلا نعتبر هذا المثال :


ID3D10Effect * effect; 
طبعا باستعمال المؤشرات يكون التعامل أسرع  و هذا مفهوم و لكن لماذا مثلا تطلب دالة ان ادخل متغير من نوع 


ID3D10Effect **effect;


فهل بهذا ستزيد السرعة أكثر أم ان هناك شىء لا افهمه ؟ 


بانتظار ردودكم

محترف  انس مشاركة 2

السلام عليكم.


بتاريخ 26 نوفمبر 2010 12:30 م، قطب Ali Amin حاجبيه بشدة وهو يقول:

أول سؤال ,  اهم فرق بين السي و السي بلس بلس , هي استعمال الكلاسات , فلو كنت تستعمل الكلاسات فأنت تستعمل لغة سي بلس بلس , طب لو كنت استعمل مزيج من الأثنين , بمعنى أكتب دوال عامة من دون كلاسات و استعمل ايضا الكلاسات , فماذا يعتبر هذا ؟ هل البرمجة الصحيحة إني اكون Full oop و لا اكتب اي شىء بخارج كلاسات ؟

حسنا لنوضح الأمور : السي لغة، و السي++ لغة اخرى. الرابط الوحيد بينهما هو ان لغة السي ++ تدعم لغة السيطبعا هناك عدة عوامل متشابهة بين اللغتين لكن يبقى الفرق جوهري بينهما.
لغة السي : لغة برمجية بنسق imperative لا املك ترجمة لهذا المصطلح لكن طريقة البرمجة تعتمد على الدوال و المتغيرات الخاصة (Structures)لغة السي ++ : تدعم البرمجة الغرضية، و ليست لغة برمجة غرضية كما هو الحال في الجافا و السي شارب. و بما انها تدعم لغة السي فانها تدعم نمط برمجة لغة السي.
الفوارق عديدة و ادعوق لقراءة مقال الاستاذ عبد اللطيف هنا في مقالات الشبكة و الذي يوضح من خلاله اهم الفوارق بين اللغتين.
اذا استعملت لغة السي++ فمن المؤسف ان تبرمج وكانك تستعمل لغة السي.فبهذا سوف تستغني على ميزات رائعة خاصة بلغة السي++ مثل الـ Template اي القوالب ، و المكتبة STL التي تعينك ايما عون في عملك .


وفي 26 نوفمبر 2010 12:30 م، أعرب Ali Amin عن رأيه بالموقف كالآتي:

مثلا لغة كالسي شارب لا تتيح لك إلا ان تكتب كل شىء بداخل كلاسات 
لانها لغة برمجية غرضية تماما،اما لغة السي++ فهي لغة برمجة تدعم البرمجة الغرضية و ليست لغة برمجية غرضية .هل اتضح الفرق ؟

في 26 نوفمبر 2010 12:30 م، قال Ali Amin بهدوء وتؤدة:

ID3D10Effect * effect; طبعا باستعمال المؤشرات يكون التعامل أسرع  و هذا مفهوم و لكن لماذا مثلا تطلب دالة ان ادخل متغير من نوع ID3D10Effect **effect;فهل بهذا ستزيد السرعة أكثر أم ان هناك شىء لا افهمه ؟ 
حسنا هل تعلم لماذا يكون التعامل اسرع ؟عادة اذا طلبت الدالة مؤشر ببعدين فهذا يعني انها تنتظر مصفوفة ببعدين(او جدول سمها كما شئت).
ماذا يعني هذا ؟انها تنتظر عنوان مصفوفة كل خانة منها تمثل مصفوفة بحد ذاتها

int *table;//مؤشر عادي
int **matrix;// مؤشر ببعدين


نتحصل على مايلي :


table = new int[10];
table[0]
table[1]
....
table[9]


matrix = new int* [10]
سنحصل على مصفوفة من المؤشرات.و كل مؤشر يمكن ان يشير الى مصفوفة تماما كما في المثال الاول، اذا
for( int i = 0;i<10;i++)
matrix[i] = new int[10];
------------------
في النهاية نحصل على التالي :
matrix[0][0]
matrix[0][1]
matrix[0][2]
...
matrix[9][0]
matrix[9][1]
matrix[9][1]







;


ارجوا ان تكون الامور اوضح.سلام

مبتدئ  Ali Amin مشاركة 3

بالنسبة للسؤال الثاني , فالامر لم يبدو لي كذلك , نعطي مثال في الدايركت اكس:
هذا المتغير الذي لدي :
ID3D10Effect *shader;
و هذه الدالة في الدايركت اكس :
HRESULT WINAPI D3DX10CreateEffectFromFileW(LPCWSTR pFileName, CONST D3D10_SHADER_MACRO *pDefines, 
ID3D10Include *pInclude, LPCSTR pProfile, UINT HLSLFlags, UINT FXFlags, ID3D10Device *pDevice, 
ID3D10EffectPool *pEffectPool, ID3DX10ThreadPump* pPump, ID3D10Effect **ppEffect, ID3D10Blob **ppErrors, HRESULT* pHResult);
فهذه الدالة تطلب مؤشر الى مؤشر 
فهذا هو مغذى سؤالي , لماذا قد تطلب دالة مؤشر الى مؤشر , و طبعا فيه الكثير من هذه الدوال نقابلها في الدايركت اكس هكذا ,  فهنا لا تعتبر مصفوفة و لها بعدين اليس كذاك ؟ فهل هذه تعتبر زيادة في السرعة ام لها فائدة أخرى ؟

محترف  انس مشاركة 4

السلام عليكم.

انا قدمت المصفوفات كمثال بسيط.
----------------------
تعديل : بعدما دققت قراءت مشاركتك، ارى انه يجب ان اعرف المزيد ع هذه الدالة حتى اتمكن من اعطاءك معلومات اكثر.
العملية اعقد بعض الشيئ اليك الرابط التالي : http://www.codeproject.com/KB/cpp/PtrToPtr.aspx#3
اذا فهمت جيدا فان هذه الطريقة تسمح للدالة بالتعامل معل مؤشر التأثير بطريقة سلسلة و كأنه مؤشر منشئ داخل الدالة. اقصد ان هذه الطريقة تسمح للدالة بمحو محتوى التاثير او تغير عنوان المؤشر حسب الضرورة.
----------------------

حسنا الهدف الرئيسي من المؤشرات هو امكانية الاحتفاظ بعنوان مساحة من الذاكرة تم حجزها بواسطة المستخدم.مثال :

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

-اعطاء المؤشر
- تذهب الدالة الى مكان المؤشر
- تجد المعلومات اللازمة في تلك المساحة.
- تعمل على تلك المعلومات(اي تعمل على الصورة مباشرة)
- انتهى


اما اذا لم تطلب مؤشر نحو الصورة و طلبة متغير من نفس نوع المتغير الذي يخزن معلومات الصورة فانظر ماذا سيحصل :

- تستقبل الذالة المتغير الذي تم ارساله لها ( وليكن المتغير الذي يخزن معلومات الصورة)
- تقوم بانشاء متغير من نفس النوع ثم تقوم بنسخ كل معلومات المتغير الذي تم استقباله في المتغير الذي تم انشاءه(اي انه اذا كان حجم المتغير المستقبل 10ميجا، فان الدال ستنشئ متغيرا اخر بنفس الحجم)
- تعمل الدالة على المتغير المنشئ و لا تعمل على المتغير المستقبل(في الحقيقة بعد ان يتم نسخ المعطيات لن تقوم الدالة باي عمل اضافي على المتغير المستقبل)
- الصورة لم تتغير لان الدالة لم تعمل عليها و انما عملت على نسخة منها.


هذه هي ميزة المؤشر، ولهذا السبب التعامل معه اسرع ، اذا فهمت هذه النقطة فما سيلي سهل ان شاء الله☺.

الان المؤشر ذو البعدين :

في المثال السابق قلنا انه اذا اردنا حجز مساحة من الذاكرة لا نعرف حجمها نستعمل المؤشرات( Dynamic Allocation).حسنا افرض مثلا انك تريد ان ترسل للدالة مجموعة من الصور فكيف ستتصرف اذا ؟هنا نستعمل المؤشر ذو البعدين. البعد الأول يشير الى مصفوفة الصور، و البعد الثاني الى الصور نفسها، لا تنسى اننا عرفنا الصورة بمؤشر.

الدالة التي قدمتها انت كمثال، لم اعمل بها، لكن المؤشرات ببعدين دورها الاساسي هو الذي ذكرته الان : المؤشر الاول : يؤشر نحو مصفوفةالمؤشر الثاني و الذي هو خانة من خانات المصفوفة التي يشير لها المؤشر الأول، يشير الى الصورة.


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

مبتدئ  Ali Amin مشاركة 5

شكرا لك , لقد فهمت الأمر  :)


و ارجو ان تقبلني على الإيميل .

محترف  انس مشاركة 6

تم تعديل مشاركتي ارجوا ان تكون قد لا حظت ذلك
أما عن الايميل فبكل سرور، لكني لم اتلقى اي شيئ اخي الكريم، هاهو ايمايلي anasmostefaoui عندالبريد الالكتروني hotmail.com

خبير مدير وسام البهنسي مشاركة 7

في 20/ذو الحجة/1431 12:11 م، قال Ali Amin بهدوء وتؤدة:

فهذا هو مغذى سؤالي , لماذا قد تطلب دالة مؤشر الى مؤشر , و طبعا فيه الكثير من هذه الدوال نقابلها في الدايركت اكس هكذا ,  فهنا لا تعتبر مصفوفة و لها بعدين اليس كذاك ؟ فهل هذه تعتبر زيادة في السرعة ام لها فائدة أخرى ؟

لا علاقة لسرعة الأداء هنا. هذا النمط من الإجراءات (يأخذ مؤشر بعد ثاني كمتغير) شائع في دايركت إكس خاصة. وهو في هذه الحالة لا يعني أنه يتوقع منك مصفوفة ثنائية البعد، وإنما يعني أنه يطلب منك متغيراً من نوع مؤشر، وسيملأ لك قيمته. كي يملأ قيمته يحتاج إلى عنوانه، وهكذا يصبح مؤشر من الدرجة الثانية...
 
عندما تواجه هذه التركيبة، فهذا يعني أنك لست أنت المسؤول عن حجز ذاكرة الكائن وإنما الإجراء الذي تستدعيه يفعل ذلك. فمثلاً إجراء CreateTexture في الواجهة IDirect3DDevice9 يطلب مؤشر درجة ثانية لواجهة IDirect3DTexture9. والأصح قول: يطلب عنوان مؤشر لواجهة IDirect3DTexture9.
 
النداء يتم بالشكل الآتي:
 


IDirect3DTexture9 *myTexture = NULL; // دائماً يفضل تهيئة المؤشرات بقيمة العدم
 
// نريد إنشاء إكساء
pD3DDevice9->CreateTexture(512,256,1,0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,&myTexture,NULL);
 
// لو نجح النداء السابق، فالآن مؤشر الإكساء تم ملؤه ويمكن التعامل معه
int levelCount = myTexture->GetLevelCount();
 
تمام؟ ☺

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

مبتدئ  Ali Amin مشاركة 8

في 28 نوفمبر 2010 06:05 ص، غمغم وسام البهنسي باستغراب قائلاً:

فهذا هو مغذى سؤالي , لماذا قد تطلب دالة مؤشر الى مؤشر , و طبعا فيه الكثير من هذه الدوال نقابلها في الدايركت اكس هكذا ,  فهنا لا تعتبر مصفوفة و لها بعدين اليس كذاك ؟ فهل هذه تعتبر زيادة في السرعة ام لها فائدة أخرى ؟
لا علاقة لسرعة الأداء هنا. هذا النمط من الإجراءات (يأخذ مؤشر بعد ثاني كمتغير) شائع في دايركت إكس خاصة. وهو في هذه الحالة لا يعني أنه يتوقع منك مصفوفة ثنائية البعد، وإنما يعني أنه يطلب منك متغيراً من نوع مؤشر، وسيملأ لك قيمته. كي يملأ قيمته يحتاج إلى عنوانه، وهكذا يصبح مؤشر من الدرجة الثانية...
 
عندما تواجه هذه التركيبة، فهذا يعني أنك لست أنت المسؤول عن حجز ذاكرة الكائن وإنما الإجراء الذي تستدعيه يفعل ذلك. فمثلاً إجراء CreateTexture في الواجهة IDirect3DDevice9 يطلب مؤشر درجة ثانية لواجهة IDirect3DTexture9. والأصح قول: يطلب عنوان مؤشر لواجهة IDirect3DTexture9.
 
النداء يتم بالشكل الآتي:

IDirect3DTexture9 *myTexture = NULL; // دائماً يفضل تهيئة المؤشرات بقيمة العدم
 
// نريد إنشاء إكساء
pD3DDevice9->CreateTexture(512,256,1,0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,&myTexture,NULL);
 
// لو نجح النداء السابق، فالآن مؤشر الإكساء تم ملؤه ويمكن التعامل معه
int levelCount = myTexture->GetLevelCount();
 
تمام؟ ☺
تمام فهمت الموضوع☺

لو لم تأتي اضافة مني يا ريت تضفني : gindisginids At Hotmail.com

محترف  انس مشاركة 9

تم 😄

مبتدئ  Ali Amin مشاركة 10

معلش كتبت الإيميل خطأ المفروض : gindisgindis At hotmail.com