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

عيوب السي++

مغلق
بدأه CompuM4n في 1 ديسمبر 2003 · 9 رد · 4,690 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

كأي لغة برمجة هناك عيوب ومميزات للسي++

و تعتبر لغة السي++ من اللغات التي تتطغى مميزاتها على عيوبها.

ولكن هذا لا يمنع من وجود العيوب. ولتخطي هذه العيوب يجب تفنيدها.

كل ما أطلبه منكم هو وضع ما ترونه عيوباً في السي++ وسأبدأ أنا.

من المعروف أن لغة السي++ case sensetive حساسة تجاه الحروف من ناحية الكابيتال والسمول والبعض يعتبر هذا عيباً بينما يعتبره البعض زيادة في عدد الكلمات الممكنة.

أرجو المشاركة بما تعرفون وشكراً.................

#2

السلام عليكم ,,,

مشكورين أخي العزيز CompuM4n على المبادرة الطيبة التي ستعلم الناس أمور لغتهم بشكل أفضل ,,

فلا خير من تعلم لغة برمج أكثر من توضيح عيوبها ومحاسنها ومقارنتها باللغات الاخرى ,,

ولكل وجهة نظر,,

من وجهة نظري فأنا أرى أن السي++ كاملة فعلا ,, لاينقصها شيء مطلقا ,,فقط عيوب طفيفة يمكن التغاضي عنها ,,

وكل الامور التي في لغات البرمجة الأخرى الاحدث من السي++ مفاهيمها مشتقة منها ,,

الان لنثري النقاش بشكل أفضل سأبين الامور الجيدة في السي++ والتي يعتبرها البعض عيوبا والتي تم استبدالها وفي الغالب حذفها من اللغات الجديدة أمثال الجافا والسي# ,,

أولا :

case sensetive في رأي ميزة لكنها متعبة أحيانا ,,

لكن كل من يعتاد عليها سيحس أن الدنيا ضيقة بدونها ,, وهي فعلا كذلك ,,

الان خذ عندك مثلا لمشاكل عويصة في تعدد الاسماء ,, لنفرض أن لدينا متغير اسمه rect معرف خارجيا بحيث أنه ليس ملك لأي دالة أو أي فئة ,, ملك للبرنامج ككل ,,

ومتغير اخر اسمه rect معرف لفئة ,,

ومتغير اخر اسمه rect سيمرر لدالة ,, واخر اسمه rect أيضا سيعرف داخل دالة ,,

وهذه الدالة في الاصل معرفة للفئة التي فيها المتغير rect ,,

وكتبنا كود هذه الدالة وليكن اسمها GetRect ,,

وقلنا في لحظة معينة rect =10 ,, فأي rect من الاربعة سيعتبرها المصرف ,, ؟!!!!

لذا يلجأ المبرمجون لوضع قواعد عامة لأنفسهم ,, مثلا أي متغير خارجي يجب أن يكون كله كابيتال ,, RECT ,,

وأي متغير معرف داخل دالة سيكون كله small ,, rect

وأي متغير ممر لدالة سيكون فقط أول حرف منه كابيتال ,,

وأي متغير معرف لفئة سيكون يبدأ بالبادئة m_ يعني m_rect ,,,

هكذا دون تعدد هذه الاسماء سندخل في ورطة كبيرة ينبغي علينا حفظ الكثير من الاسماء للمتغيرات وهو ماسيصبح مستحيلا عند تضخم البرامج ,,,

وأيضا البنى Struct المعرف والمبيته لنظام التشغيل داخ ملفات ال dll الموجودة ,, تعارفو على أن تكون كلها بالكابيتال ,,

فهي أمر رائع لتذكر الاسماء الكثيرة ,, وهي نعمة يحسدنا عليها مبرمجو الفيجوال بيسك :)

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

ثانيا :

اذا كتبنا التالي في كود

( if (x=10 ,, الملاحظ ان هذه الجملة لن تفعل الشيء المطلوب للمبرمج بالتأكيد كان يقصد كتابة

( if(x==10 وهو المطلوب ,,

الجملة الاولى ليس لها أي معنى سوى أنها ستمرر القيمة 10 للمتغير x وسيرجع أمر ال if القيمة true دائما ,, ليس لهذا أي معنى سوى اختصار بعض الاسطر ,,

المفاجيء أن مصرف لغة السي# سعتبر أن هذا خطأ ولن يعمل ابرنامج ,,

انما مبرمج السي++ فلن يعتبر المصرف بأن هناك أي خطأ وسيفترض ان المبرمج يعرف مايفعل !!!

,,,,

سنتناول المرة القادمة المزيد من هذه الاشياء ,,

banner_60_468.gif

NOTHING IS IMPOSSIBLE

#3

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

شكراً أخي HGB على هذا الطرح.

أعتقد أن ما قلته في إمكانية تعدد إستخدام الإسم في أكثر من مكان في البرنامج هو مايعتبر في مفاهيم البرمجة عيباً فعلى سبيل المثال:

إذا كان لدي إجراء في ال public أي في بداية الclass وأردت أن أستدعيه في الmain وليكن Sum وأخطأت في كتابته عند الإستدعاء وكتبته sum فإن الcompiler لن يتعرف عليه.

بينما في لغة مثل البيسك أو الباسكال فإنه لن يشكل مشكلة لأن الكابيتل مث السمول.

أيضاً يعيب البعض على السي++ بعض مميزاتها مثل الشمولية فبإمكان هذه اللغة عمل أي شيئ وهذا مما يزيد في تعقيد اللغة مما يراه البعض عيباً.

أرجو طرح المزيد من الأفكار للفائدة ومشكورييييييييييييييين.

#4

السلام عليكم,

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

فمثلا حسب تجربتي الخاصة مررت بعدة لغات وقد استقرت بين س++ والأسمبلر وقد أعجبني س++ كثيرا.

في الباسكال كنت أكره النقطتان : عند إعطاء أي متغير قيمته.

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

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

بالنسبة ل س فقد أعتبرهما في نفس المستوى مع تفوق ل س++ في ميدان البرمجة OOP .

وكما أريد أن أقول أن عيبا ما عند مبرمج ليس هو بالضرورة عند مبرمج آخر.فمثلا في الباسيك قد نستعمل أي متغيرة بدون أن نعلنها من قبل أما في س++ فيجب إعلان كل المتغيرات قبل أن نستعملها ففي البداية وحين تكون برامجنا صغيرة قد تبدو لنا هده ثقيلة لكن قد تفيدنا كثيرا حين تكبر البرامج وتكثر فيه المتغيرات.

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

الشيء الجميل الدي أعجبني في س++ أو س وهو استعمال ++ لزيادة 1 لمتغير ما فقد يبدو هدا بديهيا لكن إدا راينا هدا تحت المجهر فنرى أن له معناه الخاص ولا سيما للدين مروا عن الأسمبلر.

هده مجرد مبادرة أولى وأتمنى أن تكون لنا عودة أخرى في اقتراحات أخرى إن شاء الله.

أتمنى التوفيق للجميع وإلى اللقاء.

#5

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

أشكركم على الإهتمام. واستكمالاً لما يعتبر من عيوب السي++ هي وجود تعابير لها نفس العمل وهذا يعتبر في مفاهيم لغات البرمجة confusion مثلاً:

x=x+1

x++

++x

هذه الثلاث تعبيرات يمكن أن تقوم بنفس العمل مما يشكل إرتباك للمبرمج.

وهناك العديد من التعبيرات المتوافقة في العمل المختلفة في الشكل في السي++.

على العموم بالنسبة لي لا يشكل هذا الأمر مشكلة طالما أني أفهم كل تعبير وعمله

لكن هذا ما يقوله البعض وشكراً............

#6

السلام عليكم ,,

جميل ,, جميل ,, مشكورين أخواني chik and CompuM4n ,,,

أوافق أخي chik على أن تمهيد نوع المتغيرات أمر مزعج في بداية كل أمر ,, لكن يمكن لمبرمج الفيجوال بيسك أن يقع ي فخ سيء ,, اذا كتب اسم متغير حسب أنه قد مهد له كنوع float لكن المتغير الذي كتبه لم يكن قد عرفه مسبقا وبالطبع سيكون وضعه الافتراضي دون تصريح int ,, وكتب هذا المبرمج كود لمعادلة تضرب متغير مبرمجنا المغوار باخر float في معادلة طويلة ,, ستكون النتائج جيده لأن نتيجة الاعادة ستكون float لكن لن تكون هي النتيجة الصحيحة ,, دائما ماسيكون هناك خطأ "قد يكون قاتلا أحيانا " وهو خطأ بتر المتغير الاول ليصبح صحيحا بدل عائم float ,, وهكذا لن يعرف المبرمج الخطأ الا أن يتغمده الله برحمته ,, حيث النتائج منطقية وفي نفس الوقت المصرف لايعترض مطلقا ,,

هذه الحالة التي يعتبرها بعض مبرمجي السي++ تقيديا يجب تمهيد النوع دائما ,,

لكن هذا التقييد لم يتم بالشكل الأكثر جدية ,,, المتعصبون في لغات البرمجة يفترضون أنه يجب أن يمهد لنوع المتغير ولقيمته أيضا ,,,

الان كل المتغيرات التي تمهد بنوع int مثلا ولا تعطى قيمة يعني تكون :

int y

اذا مهدت داخل دالة ستعطى القيمة الخاصة بعنوانها الذي حجزه المصرف وهي دائمة قيمة غير مرغوب بها ,,

واذا تم استخدامها مثلا في دالة لحساب الاس ,, دون أن تمهد بالقيمة واحد ستكون النتائج مريعة في النهاية,,

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

أما لو كان معرف خارجي ,, خارج أي فئة وأي دالة فسيعطى القيمة صفر بشكل افتراضي ,,,

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

أيضا من الأمور المثيرة للجدل الجملة break داخل العبارة switch ,, خذ المثال :

switch (i)

{

: case 10

cout <<10

break

: case 15

: case 20

cout <<15<<20

break

: case 3

cout <<3

break

}

هذا المثال سيعمل في سي++ ولن يعمل في سي# !!!

يفترض مصرف السي# وجود break بعد كل انتهاء من جملة case واحدة ,,,

لكن مصرف السي++ يجعل الحبل على الغارب ولايهتم ويفترض مرة أخرى أنك تعرف ماتفعل ,,,

فمثلا ال case الاولى اذا كانت قيمة 10 اطبع 10 ,,

وال case الثالثة ,,, اذا كانت قيمة i 3 اطبع 3 ,,,

لكن ال case الثانية التي في المنتصف ,, اذا كانت i تساوي 15 أو 20 فاطبع 15 و20 ,,

لايمكن فعل شيء كهذا في السي# الا باستخدام جملة if ,,,

فأعتقد أن الحرية شيء رائع فعلا ,,,

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

أخيرا بلنسبة لأمر عامل التزايد والتناقص ++ -- فهما امران رائعان جدا ولاأدري كيف ستكون الحياة بدونهما ,,,

ولغة السي في الاصل لغة اختصارات ,, تختصر لك ماتريد فعله بجمل مرنة جدا تتشكل بأوجه كثيرة تعطي في النهاية الامر المطلوب ,,

الان فعلا لو افترضنا أن

x=x+1 شيء رائع ولا داعي لمعرف أمور أخرى حتى لاتحدث "الربكة " خذ عندك مثلا :

[ int x[10

int z=0

الان أريد أن أعين القيمة 10 للعنصر الثاني ذو العنوان 1 من المصفوفة x ,,ستكون بعامل التزايد,,

x[++z] = 10

يمكن بالطريقة العادية كتابتها ,,

x[z=z+1] = 10

ويمكن كتابتها بطريقة ثالثة

x[z+=1] = 10

الثلاث طرق الفائته ستعين القيمة 10 للعنصر الثاني من المصفوفة ,,

لكن ماذا لو أردنا أن نعين القيمة 7 للعنصر الاول ذو العنوان 0 ؟؟

[ int x[10

int z=0

باستخدام عامل التزايد ++ ,,

x[z++] = 7

المر سهل سطر واحد لكن لاحظ العلامة ++ اتت هنا بعد المتغير z وليس قبله ,, كما في المثال السابق,, هنا نقول زد قيمة z بواحد لكن بعد تنفيذ الجملة ,, وليس قبل تنفيذها كما في المثال السابق ,,

لوأردنا أن نكتب هذا المثال بالطريقة العادية ,,, ستكون

z=z+1

x[z] =7

لايمكن أن تكون في جملة واحدة ,,,

فالأمر له حسناته فعلا ,,

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

الا هنا أكتفي ,,,وهناك المزيد فيي المرة المقبلة باذن الله ,,,

banner_60_468.gif

NOTHING IS IMPOSSIBLE

#7

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

أشكر الأخوين العزيزين chik و HGB على تفاعلهما المفيد

يبدو أن لغة السي++ هي أفضل لغة برمجة موجودة فهي تعطيك قوة الأسمبلي وتحكمها

وتعطيك مرونة عالية وشمولية تصل إلى الذكاء الإصطناعي وقواعد البيانات وغيرها

وتعطيك سهولة اللغات البسيطة مثل البيسك وغيرها

رغم وجود لغة قديمة تدعى smalltalk والتي يعتبرها المبرمجين القدامى أفضل من السي++ في ال OOP . لكن السي++ هي الأكثر إنتشاراً.

ولهذا تعتبر لغة نظم التشغيل.

رغم بعض العيوب ولعلي أذكر أحد العيوب الخطيرة:

if(x!=10)

{

int x=10;

cout<<x;

}

int x=10;

cout<<x;

نلاحظ أن المتغير x الأول يختلف عن x الثاني رغم أن لهما نفس الإسم ونفس القيمة

لكن x الأولى متغير محلي local خاص بما بين أقواس if فقط

وبالتالي يجب تعريف المتغيرين ولن يعطيك الكومبايلر خطأ إعادة التعريف

بل على العكس سيعطيك خطأ عدم التعريف إذا لم تعرف x الثانية

وهنا تكمن الخطورة في التسمية

أرجو الرد وإثراء الحوار ومشكورييييييييييييين............

#8

السلام عليكم,

أشكر الأخ HGB على التوضيح وعلى كتابته الشيقة.

أريد أن أضيف فيما يتعلق بالأمر ++ أو -- أن لهادان الأوامر أرقامهما الخاصة في لغة الآلة وتعبر في الأسمبلر ب inc للأولى و dec للثانية ولزيادة 1 لقيمة الرجستر ax مثلا يمكن أن نعمل كما يلي :

mov ax,value

add ax,1

ميمكن أن نستعمل inc كما يلي

mov ax,value

inc ax

ونفس الشيء لنقص 1

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

وكما دكر الأخ CompuMan حول انتشار س++ أضن أن شركة الوندوز ربما ساهمت نوعيا في هدا إد حيث نشاهد دوال API كأنها خصصت لمبرمجي س++.

إلى اللقاء.

#9

السلام عليكم ,,,

بداية بارك الله فيكم جميعا ,,

بالنسبة لتعريف المتغيرات في المجالات المتداخلة والمجال هو ال scope ,, اقول مرة أخرى أن هذه ميزة للحذرين وفعلا خطرة لمن لايهتم بأصول كتابة الكود ,,

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

بالنسبة لمثال أخي العزيز CompuM4n فالمصرف سيفعل الشيء الصواب دائما وهو أمر رائع ,, لأن المتغير x الذي في مجال if سيتم تدميره فورا عند الخروج من مجال ال if ولن يصبح له وجود وبهذا نكون ضربنا عصفورين بحجر ,, لاتداخل في الاسماء ولاداعي لتكثيرها ,, وفي نفس الوقت حررنا الذاكرة الخاصة بالمتغير الذي انتهى مجاله !!!

الان توجد ميزة ثالثة خذ عندك المثال :

#include <iostream.h>

int x =10;

void main()
{

	int x =7;

	cout << x; //Present 7;
	cout << ::x; // Present 10 ,, The Global Sccope 
}

لاحظ المتغير x الخارجي في المجال العام ,, والمتغير الذي في الدالة في مجال الدالة ,,

كما لاحظتم الذي يحدد المجال هي الاقواس {} ,,بدون أن تكتب if while أو أي شيء من هذه الامور فقط أقواس !!

الان يمكنك استخدام أي x تريد , الداخلية أو الخارجي ,, بطريقة رائعة ولاتورث أي مشاكل ,, حيث لاتوجد أخطاء عدم انتباه هنا ,,,طبعا باستخدام العمل :: والذي يسمى عامل دقة المجال ,, المتغير ذو :: هو المتغير الذي في المجال الخارجي دائما ,,

والذي بدون تحديد للمدى هو المتغير الذي في أصغر مجال حالي ,,,

هذا أمر ,, أمر اخر التحكم في الذاكرة !! شيء رائع أن تكتب الكود لتكون المتغيرات في المكدس ويتم تنظيفها فورا عند الانتهاء من الحاجة اليها ,, لذا قاعدة عامة حاول أن تجعل هندسة برنامجك بأفضل صورة بحيث تجعل للمتغيرات أصغر مجال ممكن ,,

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

,,,,,,,,,,,,,,,,,,,

وفعلا كما ذكر أخي chik بالنسبة لعامل التزايد والتناقص ++ -- أنهما قد يكونان أكثر سرعة في التنفيذ من النسخة العادية ذات ال add وهي في السي ++ ,,

++X أسرع من X=X+1 ,,,

والسبب في ذلك لأنه توجد تعليمة اضافية معرف في ال MicroProcessor "المعالج " لها ترميز ثنائي خاص بها " اذا كانت هناك تعليمة مدعمة في المعالج فأمر السرعة الخاص بها يتعلق بسرعة الكهرباء فيي المعالج فقط " ,,

أقول فعلا قد تحتاج هذه التعليمة ربما الى أكثر من دورة Processor لتنفيذها وقد تحتاج لدورة واحدة ,, فاذا كانت عدد دورات ال Processor الخاصة ب Inc مثلا أقل من ال Add فهذا بالتاكيد يعني أن السرعة هنا أكبر ,, وبالمناسبة المصرف الفيجوال ذكي بشكل جيد بحيث ينتج الكود النهائي في ملف ال EXE صاحب أقل عدد دورات Processor ,,

,,,,,,,,,,,,,,,,,,

وبالنسبة لأنتشار السي++ فهي اللغة الاقوى حتى الان ,, وتمت كتابة أنظمة التشغيل كلها تقريبا بالسي من اللينكس واليونكس والماك كلها الا القديمة جدا ,, والوندوز كله مكتوب بالسي والاسمبلي ,, ملفات ال dll ,,

فأمر طبيعي أن يتم تطوير النظام كل مرة باستخدام نفس اللغة ,,,

والدوال التي في ملفات ال dll يمكن لمبرمجي الفيجوال بيسك استخدامها "أغلبها " ماعدا تلك المكتوبة بطريقة الاستدعاء cdecl_ أمثال printf ,,,,

,,,,,,,,,,,,,,,,,,

أمر جديد أذكره هنا بخصوص الوراثة المتعددة ,, فقد تم حذفها من السي# ,, يمكن للفئة العادية في سي++ أن ترث من أكثر من فئة أخرى ,, في هذا مشكلة عويصة تدعى بالشكل الماسي ,,, لايتسع المجال لشرحها وسأشرحها ببعض التفصيل في جلسات ال OOP في المنتدى هنا ,,

عموما كثر الجدل والنقاش حول الوراثة المتعددة وأنه يمكن كتابة هندسة فائقة دون استخدامها ,, عموما لكل رأيه ,, لكن مبرمج السي++ اذا لم يكن حذرا فسيأكل ناره ,,

وفي السي++ يمكن أن ترث فئة من فئة أو عدة فئات أو واجهة interface_ أو عدة واجهات أو كليهما معا ,,,

أما السي# يمكن أن ترث الفئة فقط من فئة واحدة و عدة واجهات ,,,

,,,,,,,,,,,,,,,,,,

ومازال هناك الكثير من هذه الامور ,, سنتطرق اليها بالتقسيط ,,,

وبارك الله فيكم ,,

banner_60_468.gif

NOTHING IS IMPOSSIBLE

#10

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

أشكرك أخي HGB على التوضيح

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

بالنسبة لل OOP فهي بحر جديد في البرمجة نريد مواضيع تفصيلية عنه أو على الأقل نحن درسناه بشكل عام ياليت إذا كان هناك مميزات قوية معروفة تذكرها لنا فموضوع جديد ونكون لك من الشاكرين (سواء HGB أو أي مبرمج آخر)

الكل فيهم الخير والبركة وانتم كرماء واحنا نستاهل.

هذا الموضوع مغلق.

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