سؤال

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

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string filename = "testfile";      
    std::ifstream fin;

    fin.open(filename.c_str()); // Works just fine.
    fin.close();

    //fin.open(filename); // Error: no such method.
    //fin.close();
}

هذا يحصل لي طوال الوقت عند العمل مع الملفات.بالتأكيد سوف تستخدم مكتبة C++ std::string حيثما كان ذلك ممكنا؟

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

المحلول

عن طريق أخذ سلسلة C C++ 03 std::fstream الطبقة تقلل الاعتماد على std::string فصل.في C++ 11، ومع ذلك، فإن std::fstream الفصل يسمح بتمرير أ std::string لمعلمة المنشئ الخاصة به.

الآن، قد تتساءل لماذا لا يوجد تحويل شفاف من ملف std:string إلى سلسلة C، لذا فإن الفصل الذي يتوقع سلسلة C لا يزال بإمكانه أن يأخذ std::string تمامًا مثل الفصل الذي يتوقع أ std::string يمكن أن تأخذ سلسلة C.

والسبب هو أن هذا من شأنه أن يسبب دورة تحويل، والتي بدورها قد تؤدي إلى مشاكل.على سبيل المثال، لنفترض std::string سيكون قابلاً للتحويل إلى سلسلة C بحيث يمكنك استخدامه std::stringمع fstreamس.لنفترض أيضًا أن سلسلة C قابلة للتحويل إليها std::strings كما هي الحالة في المعيار الحالي.الآن، خذ بعين الاعتبار ما يلي:

void f(std::string str1, std::string str2);
void f(char* cstr1, char* cstr2);

void g()
{
    char* cstr = "abc";
    std::string str = "def";
    f(cstr, str);  // ERROR:  ambiguous
}

لأنه يمكنك التحويل في كلتا الحالتين بين a std::string وسلسلة C المكالمة إلى f() يمكن أن تحل على أي من الاثنين f() البدائل، وبالتالي فهي غامضة.الحل هو كسر دورة التحويل عن طريق جعل اتجاه تحويل واحد واضحًا، وهو ما اختارت المحكمة الخاصة بلبنان أن تفعله c_str().

نصائح أخرى

هناك العديد من الأماكن التي لم تقم فيها لجنة معايير C++ بتحسين التفاعل بين المرافق في المكتبة القياسية.

std::string واستخدامه في المكتبة هو واحد من هذه.

أحد الأمثلة الأخرى هو std::swap.تحتوي العديد من الحاويات على وظيفة عضو المبادلة، ولكن لا يتم توفير التحميل الزائد لـ std::swap.الشيء نفسه ينطبق على std::sort.

آمل أن يتم إصلاح كل هذه الأشياء الصغيرة في المعيار القادم.

ربما هو عزاء:حصلت جميع ملفات fstream على open(string const &,...) بجوار open(char const *,...) في مسودة العمل لمعيار C++0x.(انظر على سبيل المثال27.8.1.6 لإعلان basic_ifstream)

لذلك عندما يتم الانتهاء منه وتنفيذه، فلن يفيدك بعد الآن :)

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

@ برنارد:
متراصة "Unstrung". "الكل من أجل واحد ، وواحد للجميع" قد يعمل مع Musketeers ، ولكنه لا يعمل أيضًا لمصممي الفصل.فيما يلي مثال ليس مثاليًا تمامًا، وهو يوضح مدى سوء الخطأ الذي يمكن أن ترتكبه عندما يتحول التصميم إلى تصميم زائد.المثال للأسف مأخوذ من مكتبة عادية قريبة منك...~ http://www.gotw.ca/gotw/084.htm

إنه أمر غير منطقي، هذا صحيح.ماذا تقصد بكون واجهة std::string كبيرة؟ماذا يعني كبير في هذا السياق - الكثير من استدعاءات الطريقة؟أنا لا أتظاهر بالسخرية، أنا مهتم بالفعل.

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

أعتقد أن المشكلة الحقيقية هي أن مكتبة C++ تتكون من ثلاثة أجزاء؛فهو يحتوي على مكتبة C القديمة، ويحتوي على STL، ويحتوي على سلاسل وiostreams.على الرغم من بذل بعض الجهود لجسر الأجزاء المختلفة (على سبيل المثال.إضافة التحميل الزائد إلى مكتبة C، لأن C++ يدعم التحميل الزائد؛إضافة التكرارات إلى basic_string؛(إضافة محولات مكرر iostream)، هناك الكثير من التناقضات عندما تنظر إلى التفاصيل.

على سبيل المثال، تتضمن basic_string أساليب تعتبر تكرارات غير ضرورية للخوارزميات القياسية؛من المحتمل أن تتم إزالة طرق البحث المختلفة بأمان.مثال آخر:تستخدم اللغات المؤشرات الأولية بدلاً من التكرارات.

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

لم يكن لدينا آلاف الميجابايت من ذاكرة الوصول العشوائي لنستخدمها كما نفعل اليوم.لم يكن لدينا عادةً ارتباط على مستوى الوظيفة، لذلك كنا تحت رحمة مطور المكتبة لاستخدام الكثير من ملفات الكائنات المنفصلة أو سحب الكثير من التعليمات البرمجية غير المطلوبة.كل هذا FUD جعل المطورين يبتعدون عن std::string.

في ذلك الوقت تجنبت std::string أيضًا."منتفخ جدًا"، "يُسمى malloc كثيرًا"، وما إلى ذلك.استخدام المخازن المؤقتة المستندة إلى المكدس للسلاسل بحماقة، ثم إضافة جميع أنواع التعليمات البرمجية المملة للتأكد من عدم تجاوزها.

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

أعتقد أن هذا قد تم التفكير فيه وتم القيام به لتجنب التبعية؛أي.#include <fstream> لا ينبغي أن يجبر المرء على #include <string>.

لكي نكون صادقين، يبدو أن هذه مسألة غير منطقية تمامًا.السؤال الأفضل هو، لماذا واجهة std::string كبيرة جدًا؟

في الوقت الحاضر يمكنك حل هذه المشكلة بسهولة شديدة:يضيف -std=c++11 لك CFLAGS.

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