ما الذي يمكن أن يفعله C ++ هذا صعبًا جدًا أو فوضويًا في أي لغة أخرى؟

StackOverflow https://stackoverflow.com/questions/423335

  •  05-07-2019
  •  | 
  •  

سؤال

ما زلت أشعر أن C ++ يقدم بعض الأشياء التي لا يمكن التغلب عليها. ليس نيتي أن أبدأ حرب اللهب هنا ، من فضلك ، إذا كان لديك آراء قوية حول عدم الإعجاب بـ C ++ ، فلا تنفيسهم هنا. أنا مهتم بالسماع من C ++ Gurus حول سبب التمسك بها.

أنا مهتم بشكل خاص بجوانب C ++ غير معروفة أو غير مستغلة.

يحرر: الناس ، يرجى أن يكون لديهم على الأقل قراءة سريعة عن الردود الأخرى للتأكد من أنك لا تكرر ما قيل بالفعل ، إذا كنت توافق على ما قاله شخص آخر ، قم بتصويته!

هل كانت مفيدة؟

المحلول

لقد بقيت مع C ++ لأنه لا يزال أعلى لغة للأغراض العامة للتطبيقات التي تحتاج إلى الجمع بين الكفاءة و تعقيد. على سبيل المثال ، أكتب برنامج نمذجة السطح في الوقت الحقيقي للأجهزة المحمولة اليدوي لصناعة المسح. بالنظر إلى الموارد المحدودة ، فإن Java و C#، وما إلى ذلك ... فقط لا توفر خصائص الأداء اللازمة ، في حين أن لغات المستوى الأدنى مثل C أبطأ كثيرًا في تطوير خصائص التجريد الأضعف. إن مجموعة مستويات التجريد المتاحة لمطور C ++ ضخم ، في أحد المتطرفين ، يمكن أن أكون مشغلات حسابية مثقلة بحيث يمكنني قول شيء مثل MaterialVolume = Designsurface - Groundsurface بينما في نفس الوقت تشغيل عدد من أكوام مختلفة لإدارة الذاكرة بشكل أكثر كفاءة في تطبيقي على جهاز معين. اجمع هذا مع مجموعة من المصدر المتاح بحرية لحل أي مشكلة شائعة إلى حد كبير ، ولديك إحدى لغة التنمية القوية.

هل لا يزال C ++ هو حل التطوير الأمثل لمعظم المشكلات في معظم المجالات؟ ربما لا ، على الرغم من أنه في قرصة لا يزال من الممكن استخدامه لمعظمهم. هل ما زال الحل الأفضل للتطوير الفعال للتطبيقات عالية الأداء؟ IMHO دون أدنى شك.

نصائح أخرى

Raii / الانتهاء الحتمي. لا ، جمع القمامة ليس كذلك بنفس الجودة عندما تتعامل مع مورد نادر ومشترك.

الوصول غير المقيد إلى APIs OS.

إطلاق النار على نفسه في القدم.

لا توجد لغة أخرى تقدم مثل هذه المجموعة الإبداعية من الأدوات. المؤشرات ، والميراث المتعدد ، والقوالب ، والحمل الزائد للمشغل والمعالج المسبق.

لغة قوية رائعة توفر أيضًا فرصًا وفيرة لإطلاق النار على القدمين.

تحرير: أعتذر إذا كانت محاولتي العرجاء في الفكاهة قد أساءت بعضها. أنا أعتبر C ++ هي اللغة الأقوى التي استخدمتها على الإطلاق - مع قدرات على الترميز على مستوى لغة التجميع عند الرغبة ، وفي مستوى عالٍ من التجريد عند الرغبة. لقد كانت C ++ لغتي الأساسية منذ أوائل التسعينيات.

كانت إجابتي تستند إلى سنوات من الخبرة في إطلاق النار على نفسي. على الأقل C ++ يسمح لي بالقيام بذلك بأناقة.

تدمير الكائن الحتمي يؤدي إلى بعض أنماط التصميم الرائعة. على سبيل المثال ، على الرغم من أن RAII ليس تقنية عامة مثل مجموعة القمامة ، إلا أنه يؤدي إلى بعض القدرات المثيرة للإعجاب التي لا يمكنك الحصول عليها مع GC.

يعد C ++ فريدًا أيضًا من حيث أنه يحتوي على معالج مسبق ترينو. يتيح لك ذلك تفضيل (كما هو الحال في عكس التأجيل) الكثير من مهام التعليمات البرمجية لتجميع الوقت بدلاً من وقت التشغيل. على سبيل المثال ، في التعليمات البرمجية الحقيقية ، قد يكون لديك بيان Assert () لاختبار لمحاضرة لا تقم. والحقيقة هي أنه سيحدث عاجلاً أم آجلاً ... ويحدث في الساعة 3:00 صباحًا عندما تكون في إجازة. يؤكد المعالج المسبق C ++ نفس الاختبار في وقت الترجمة. تؤكد التأكيد على التأكيد بين الساعة 8:00 صباحًا و 5:00 مساءً أثناء الجلوس أمام الكمبيوتر تشاهد الكود ؛ تأكد وقت التشغيل في الساعة 3:00 صباحًا عندما تكون نائماً في هاواي. من السهل جدًا رؤية الفوز هناك.

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

اكتب التجميع المضمن (MMX ، SSE ، إلخ).

تدمير الكائن الحتمي. أي المدمرين الحقيقيين. يجعل إدارة الموارد النادرة أسهل. يسمح لـ Raii.

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

ميراث متعدد. لا يمكن القيام بكل شيء مع واجهات. في بعض الأحيان تريد أن ترث الوظيفة الفعلية أيضًا.

أعتقد أنني سأثني على C ++ لقدرتها على استخدام القوالب لالتقاط التعبيرات وتنفيذها بتكاسل عند الحاجة. بالنسبة لأولئك الذين لا يعرفون ما يدور حوله هذا ، هنا انه مثال.

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

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

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

(حسنًا ، يمكنك القيام بذلك في C ، التجميع ، وربما Fortran أيضًا. لكن C ++ يتيح لك كتابة بقية البرنامج على مستوى أعلى.)

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

C#، على سبيل المثال ، ليس لديه منشأة ماكرو حقيقية. لا يمكنك #include ملف آخر مباشرة في المصدر ، أو استخدام #Define لمعالجة البرنامج كنص. فكر في أي وقت اضطررت فيه إلى كتابة التعليمات البرمجية المتكررة ميكانيكياً وكنت تعلم أن هناك طريقة أفضل. ربما تكون قد كتبت برنامجًا لإنشاء رمز لك. حسنًا ، يقوم المعالج المسبق C ++ بأتمتة كل هذه الأشياء.

مرفق "الأدوية" في C# محدودة بالمثل مقارنة بقوالب C ++. يتيح لك C ++ تطبيق مشغل DOT على نوع القالب T بشكل أعمى ، والاتصال (على سبيل المثال) الأساليب التي قد لا تكون موجودة ، ويتم التحقق من التصحيح فقط بمجرد تطبيق القالب فعليًا على فئة محددة. عندما يحدث ذلك ، إذا كان كل الافتراضات التي وضعتها حول T قد تمسكها بالفعل ، فسيتم تجميع الكود الخاص بك. لا يسمح C# بهذا ... يجب التعامل مع النوع "T" بشكل أساسي ككائن ، أي باستخدام أقل قاسم مشترك للعمليات المتاحة لكل شيء (التعيين ، GethashCode () ، متساوي ()).

لقد تخلصت C# مع المعالج المسبق ، والذهل الحقيقي ، باسم البساطة. لسوء الحظ ، عندما أستخدم C#، أجد نفسي أتوصل إلى بدائل لإنشاءات C ++ هذه ، والتي لا يمكن حتماً من الانتفاخ والطبقة من نهج C ++. على سبيل المثال ، لقد رأيت المبرمجين يعملون على غياب #include بعدة طرق متضخمة: الارتباط ديناميكيًا بالتجميعات الخارجية ، وإعادة تحديد الثوابت في عدة مواقع (ملف واحد لكل مشروع) أو اختيار الثوابت من قاعدة بيانات ، إلخ.

كما قالت السيدة كراببل من سيمبسون ذات مرة ، هذا "عرجاء ، ميلهاوس".

فيما يتعلق بعلوم الكمبيوتر ، تتيح ميزات وقت الترجمة هذه لـ C ++ أشياء مثل تمرير المعلمة Call-By-Name ، والتي يُعرف أنها أقوى من النداء والقيمة.

مرة أخرى ، ربما لا تكون هذه هي الإجابة الشائعة- أي نص C ++ تمهيدي سيحذرك من #Define ، على سبيل المثال. لكن بعد أن عملت مع مجموعة واسعة من اللغات على مدار سنوات عديدة ، وبعد النظر في النظرية وراء كل هذا ، أعتقد أن العديد من الناس يقدمون نصيحة سيئة. يبدو أن هذا هو الحال بشكل خاص في المجال الفرعي المخفف المعروف باسم "It".

من الناحية الفنية ، أعتقد أنه لا يوجد شيء ، حقًا!

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

الشيء الوحيد الذي يمكن أن يفعله C ++ هو أن يكون متوافقًا مع ملايين خطوط الرموز المكتوبة بالفعل في C ++.
هذا هو الشيء الوحيد الذي لا يمكن أن تفعله لغة غير C ++ :)

تمرير هياكل جراب عبر العمليات مع الحد الأدنى من النفقات العامة. بمعنى آخر ، يتيح لنا التعامل بسهولة مع النقط من البيانات الثنائية.

يجبرك C# و Java على وضع وظيفة "Main ()" في الفصل. أجد ذلك غريبًا ، لأنه يخفف من معنى الفصل.

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

لحسن الحظ ، على عكس C# و Java ، يتيح C ++ وظائف عالمية. هذا يتيح لوجود وظيفة () في الخارج. لذلك يوفر C ++ تطبيقًا أبسط وأكثر اتساقًا وربما أكثر صدقًا من المصطلح الموجهة للكائن. وبالتالي ، هذا شيء واحد يمكن أن يفعله C ++ ، لكن C# و Java لا يمكن.

أعتقد أن الحمل الزائد للمشغل هو ميزة رائعة للغاية. بالطبع يمكن أن يتعرض للإساءة إلى حد كبير (كما هو الحال في تعزيز Lambda).

السيطرة الضيقة على موارد النظام (ذاكرة esp) مع تقديم آليات تجريد قوية اختياريا. اللغة الوحيدة التي أعرفها يمكن أن تقترب من C ++ في هذا الصدد هي ADA.

يوفر C ++ تحكمًا كاملاً في الذاكرة ، ونتيجة لذلك ، يجعل تدفق تنفيذ البرنامج أكثر قابلية للتنبؤ به. لا يمكنك فقط أن تقول بدقة في أي وقت تحدث تخصيصات وتخصيصات للذاكرة ، بل يمكنك تحديد أكوامك ، ولديها أكوام متعددة لأغراض مختلفة وتقول بدقة المكان الذي يتم فيه تخصيص بيانات الذاكرة. غالبًا ما يكون هذا مفيدًا عند البرمجة على أنظمة الوقت المدمج/في الوقت الفعلي ، مثل لوحات المفاتيح للألعاب والهواتف المحمولة ومشغلات MP3 وما إلى ذلك ، والتي:

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

AFAIK ، C و C ++ هي الخيار الوحيد المعقول للقيام بهذا النوع من الأشياء.

حسنًا ، لكي تكون صادقًا تمامًا ، يمكنك فعل أي شيء إذا كنت على استعداد لكتابة كود كافي.

للإجابة على سؤالك ، لا ، لا يوجد شيء لا يمكنك فعله بلغة أخرى لا يمكن لـ C ++ القيام بها. هذا هو مقدار الصبر الذي لديك وهل أنت على استعداد لتكريس الليالي الطويلة التي لا تنام لجعلها تعمل؟

هناك أشياء تجعل أغلفة C ++ من السهل القيام بها (لأنه يمكنهم قراءة ملفات الرأس) ، مثل تطوير Office. ولكن مرة أخرى ، يرجع ذلك إلى أن شخصًا ما كتب الكثير من التعليمات البرمجية "لف" لك في RCW أو "Wranttime Call Callper"

تحرير: أنت تدرك أيضًا أن هذا سؤال محمّل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top