سؤال

لماذا نحن بحاجة إلى سواء باستخدام مساحة وتشمل التوجيهات في C++ البرامج ؟

على سبيل المثال ،

#include <iostream>

using namespace std;

int main() {
 cout << "Hello world";
}

لماذا هو لا يكفي أن يكون مجرد #include أو يكون مجرد "باستخدام مساحة الأمراض المنقولة جنسيا" والتخلص من الآخر ؟

(أنا أعتقد من القياس مع جافا, استيراد java.net.* استيراد استيراد كل شيء من java.net أنت لا تحتاج إلى القيام بأي شيء آخر.)

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

المحلول

في C++ المفاهيم منفصلة. هذا حسب التصميم ومفيد.

يمكنك تضمين الأشياء التي بدون أعداد السم غير غامضة.

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

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

نصائح أخرى

استخدام التوجيهات وتشمل توجيهات مسبقا هي شيئان مختلفان. ال include يتوافق تقريبا مع CLASSPATH متغير البيئة من جافا، أو -cp خيار الجهاز الظاهري Java.

ما يفعله هو جعل الأنواع معروفة بالمترجم. بما في ذلك فقط <string> على سبيل المثال سوف تجعلك قادرا على الرجوع إلى std::string :

#include <string>
#include <iostream>

int main() {
    std::cout << std::string("hello, i'm a string");
}

الآن، استخدام التوجيهات مثل import في جاوة. أنها تجعل أسماء مرئية في النطاق الذي تظهر به، لذلك لا يتعين عليك تأهيلها بالكامل بعد الآن. مثل في جاوة، يجب أن تكون الأسماء المستخدمة معروفة قبل أن تتم مرئيا:

#include <string> // CLASSPATH, or -cp
#include <iostream>

// without import in java you would have to type java.lang.String . 
// note it happens that java has a special rule to import java.lang.* 
// automatically. but that doesn't happen for other packages 
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String; 
using namespace std; // import java.lang.*;

int main() {
    cout << string("hello, i'm a string");
}

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

كن حذرا عند القيام بذلك على نطاق عالمي حتى في ملفات التنفيذ. من الأفضل استخدامها كمحلي قدر الإمكان. بالنسبة إلى مساحة الاسم STD، أنا لا أستخدم ذلك أبدا. أنا، والعديد من الناس الآخرين، فقط اكتب دائما std:: أمام الأسماء. ولكن إذا صادفت ذلك، ففعل ذلك مثل هذا:

#include <string>
#include <iostream>

int main() {
    using namespace std;
    cout << string("hello, i'm a string");
}

فيما يتعلق بأسماء الأسماء ولماذا تحتاج إليهم، يرجى قراءة الاقتراح الذي أعطى فيه Bjarne Stroustrup عام 1993 لإضافة معايير C ++ القادمة. انها مكتوبة بشكل جيد:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/n0262.pdf.

في C ++. #include واستخدام لها وظائف مختلفة.

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

يأتي هذا من C ++ عدم وجود مفهوم وحدة نمطية.

ضع في اعتبارك أن أسماء الأسماء في C ++ مفتوحة، وهذا يعني أن الملفات المختلفة يمكن أن تحدد أجزاء مختلفة من مساحة الاسم نفسها (نوع من الفصول الجزئية .NET).

//a.h
namespace eg {
    void foo();
}

//b.h
namespace eg {
    void bar();
}

تشمل تشمل تحديد وجود الوظائف.

الاستخدام يسهل استخدامها.

cout كما هو محدد في iOStream يدعى فعلا "STD :: Cout".

يمكنك تجنب استخدام مساحة الاسم بالكتابة.

std::cout << "Hello World";

تستخدم هذه الكلمات الرئيسية لأغراض مختلفة.

تستخدم الكلمة الرئيسية باستخدام اسم مساحة اسم متاحة للاستخدام في المنطقة الإعلانية الحالية. في الغالب للراحة حتى لا تضطر إلى استخدام الاسم المؤهل بالكامل طوال الوقت. هذه صفحة يشرح ذلك في بعض التفاصيل.

البيان #Include هو توجيه سابق في المعالج ويحكي ما قبل المعالج بمعالجة محتويات ملف محدد كما لو كانت هذه المحتويات قد ظهرت في البرنامج المصدر عند الإشارة التي يظهر فيها التوجيه. هذا هو، يمكنك التفكير في هذا البيان كنسخ الملف المضمن في واحد الحالي. ثم يقوم برنامج التحويل البرمجي بتجميع الملف بأكمله كما لو أنه كتب كل الكود في ملف واحد كبير.

أعتقد أن الإجابات الأخرى تفتقد أن النقطة قليلا. في كل من C ++، Java و C #، using/import الشيء اختياري بالكامل. لذلك هذا ليس مختلفا.

ثم عليك أن تفعل شيئا آخر لإنشاء التعليمات البرمجية مرئية على أي حال، في جميع المنصات الثلاثة.

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

وفي C # عليك إضافة إشارة إلى الجمعية الأخرى. التي تعتني بمعادل الإعدادات وربطها.

وفي Java، عليك التأكد من أن الكود موجود في ClassPath، على سبيل المثال، إضافة جرة ذات الصلة إليه.

لذلك هناك أشياء مماثلة للغاية مطلوبة على جميع المنصات الثلاثة، والانفصال بين using/import (الراحة) ودقة الربط الفعلية (متطلبات) هو نفسه في الثلاثة.

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

في حين using namespace std; ليس بالضرورة فكرة سيئة، باستخدامها لجميع المسامع المسامع القضاء على الفائدة بالكامل. أسماء الأسماء موجودة حتى تتمكن من كتابة الوحدات النمطية دون الاعتبار لاسم الاشتباكات مع وحدات أخرى، و using namespace this; using namespace that; يمكن أن تخلق الغموض.

تحتاج إلى فهم مساحات إذا كنت تريد حقا أن نفهم هذا.

مع include أنت فقط بما في ذلك ملف الرأس.

مع using namespace أنت تعلن أنك تستخدم معين مساحة الاسم التي تحتوي على أشياء مثل cout.حتى إذا كنت تفعل هذا:

using namespace std;

إلى استخدام cout يمكنك أن تفعل فقط

cout << "Namespaces are good Fun";

بدلا من:

std::cout << "Namespaces are Awesome";

ملاحظة أنه إذا كنت لا #include <iostream> أنك لن تكون قادرا على استخدام لا std::cout ولا cout في التعريفات الخاصة بك وما إلى ذلك لأنك لا بما في ذلك الرأس.

بطانة واحدة (ليس هذا شيء جديد :)):

باستخدام STD. يسمح لك بالحذف STD :: بادئة، ولكن لا يمكنك استخدام كوت. على الإطلاق دون iostream..

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

السؤال حقا هو "لماذا C ++ - بعد ذلك كان بالفعل #include آلية - إضافة مساحات الأسماء؟ "

أفضل مثال أعرف عن السبب #include لا يكفي يأتي من الشمس. من الواضح أن مطورو الشمس لديهم مشكلة مع أحد منتجاتهم لأنهم كتبوا mktemp() وظيفة حدث أن يكون لها نفس التوقيع باعتباره mktemp() الوظيفة التي تم تضمينها من خلال ملف تم تضمينه من خلال رأس المشروع مطلوب بالفعل.

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

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

كلا C # و Java (1) لها آلية مساحة الاسم (namespace في C #، package في Java)، (2) عادة ما يتم تطويرها من خلال ides التي تتعامل مع الإشارة إلى الثنائيات للمطور، و (3) لا تسمح للوظائف القائمة بذاتها (نطاق الفئة هو مساحة الاسم، ويقلل من خطر تلويث مساحة الاسم العالمية ) لذلك لديهم حل مختلف لهذه المشكلة. ومع ذلك، لا يزال من الممكن الحصول على بعض الغموض فيما يتعلق بالطريقة التي تتصل بها (على سبيل المثال، اشتباك الاسم بين واجهتين ترثا فئة)، وفي هذه الحالة تتطلب جميع اللغات الثلاث المبرمجة تحديد الطريقة التي يتم تحديدها بوضوح تبحث بالفعل عن، عادة عن طريق الإضراب اسم الطبقة / الواجهة الأصل.

في C ++، سيقوم توجيه التوجيه بنسخ ولصق ملف الرأس في التعليمات البرمجية المصدرية في خطوة ما قبل الجرعات. تجدر الإشارة إلى أن ملف الرأس يحتوي بشكل عام على الوظائف والفئات المعلنة داخل مساحة الاسم. على سبيل المثال، <vector> قد يبدو الرأس يشبه شيئا مثل هذا:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
} 

يفترض أنك بحاجة إلى تحديد متجه في وظيفتك الرئيسية، تقوم به #include <vector> ولديك قطعة من التعليمات البرمجية أعلاه في التعليمات البرمجية الخاصة بك الآن:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
}
int main(){
   /*you want to use vector here*/
}

لاحظ أنه في التعليمات البرمجية الخاصة بك فئة المتجه لا تزال موجودة في std مساحة الاسم. ومع ذلك، وظيفتك الرئيسية هي في الافتراضي global مساحة الاسم، لذلك ببساطة بما في ذلك الرأس لن تجعل فئة المتجه مرئية في global مساحة الاسم. عليك إما استخدامها using أو هل بادئة مثل std::vector.

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