متى يجب استخدام مهيئ قوائم تهيئة فئة C++ الأعضاء ؟

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

  •  06-07-2019
  •  | 
  •  

سؤال

دعونا نقول لدي std::map< std::string, std::string > m_someMap خاصة الأعضاء متغير من فئة A

سؤالين:(والسبب الوحيد الذي أطلبه هو بسبب جئت عبر رمز من هذا القبيل)

  1. ما هو الغرض من هذا السطر:

    A::A() : m_someMap()
    

    الآن وأنا أعلم أن هذا هو intialization, ولكن لا يجب أن تفعل هذا القبيل ؟ أنا في حيرة.

  2. ما هي القيمة الافتراضية std::map< std::string, std::string > m_someMap, أيضا ج# تعرف أن int, double, الخ.دائما تهيئة defualt 0 و الكائنات إلى null (على الأقل في معظم الحالات) إذن ما هي القاعدة في C++??هي كائن تهيئة قبل defualt إلى null و الأوليات إلى القمامة ؟ بالطبع أتكلم عن المتغيرات سبيل المثال.

تحرير:

أيضا ، حيث أن معظم الناس أشار إلى أن هذا هو أسلوب الاختيار وليس من الضروري ، ماذا عن:

A::A() :m_someMap(), m_someint(0), m_somebool(كاذبة)

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

المحلول

m_somemap

  1. لم يكن لديك إلى.
  2. ما تحصل عليه إذا قمت بحذف ذلك:فارغة std::map< std::string, std::string >, أي صالحة سبيل المثال من تلك الخريطة التي لديها عناصر في ذلك.

m_somebool

  1. يجب عليك تهيئة true أو false إذا كنت تريد أن يكون لها قيمة معروفة.القيم المنطقية هي "القديم عادي أنواع البيانات" وليس لديهم مفهوم منشئ.وعلاوة على ذلك, C++ لغة لا يحدد القيم الافتراضية غير صراحة-تهيئة القيم المنطقية.
  2. ما تحصل عليه إذا قمت بحذف ذلك:منطقية الأعضاء مع غير محدد القيمة.لا يجب أن تفعل هذا في وقت لاحق استخدام قيمته.لأن ذلك هو أنه يوصى بشدة السياسة التي يمكنك تهيئة كافة القيم من هذا النوع.

m_someint

  1. يجب عليك تهيئة بعض قيمة عدد صحيح إذا كنت تريد أن يكون لها قيمة معروفة.الأعداد الصحيحة هي "القديم عادي أنواع البيانات" وليس لديهم مفهوم منشئ.وعلاوة على ذلك, C++ لغة لا يحدد القيم الافتراضية غير صراحة-تهيئة الاعداد الصحيحه.
  2. ما تحصل عليه إذا قمت بحذف ذلك:الباحث الأعضاء مع غير محدد القيمة.لا يجب أن تفعل هذا في وقت لاحق استخدام قيمته.لأن ذلك هو أنه يوصى بشدة السياسة التي يمكنك تهيئة كافة القيم من هذا النوع.

نصائح أخرى

ليست هناك حاجة إلى أن تفعل ذلك في الواقع.
منشئ افتراضي سوف autmatically تفعل ذلك.

ولكن somtimes من خلال التوضيح انها بمثابة نوع من الوثائق:

class X
{
    std::map<string,string>  data;
    Y                        somePropertyOfdata;

    X()
      :data()                    // Technically not needed
      ,somePropertyOfdata(data)  // But it documents that data is finished construction
    {}                           // before it is used here.
};

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

ولكن القول.النظر في هذا:

template<typename T>
class Z
{
     T  data;   
     Z()
        :data()    // Technicall not need as default constructor will
                   // always be called for classes.
                   // But doing this will initialize POD data correctly
                   // if T is a basic POD type. 
     {}
};

هنا يمكنك أن exepect البيانات الافتراضي تهيئة.
من الناحية الفنية جراب لا يكون منشئات حتى إذا كان الباحث ثم هل تتوقع أن تفعل أي شيء ؟ لأنه كان صراحة تهيئة يتم تعيين إلى 0 أو ما يعادلها بالنسبة جراب أنواع.

Edit:

class A
{
    std::map<string,string>   m_someMap;
    int                       m_someint;
    bool                      m_somebool;
   public:
    A::A()
       : m_someMap()      // Class will always be initialised (so optional)
       , m_someint(0)     // without this POD will be undefined
       , m_somebool(false)// without this POD will be undefined
    {}
};

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

A::A() : m_someMap()

هذا الخط هو غير ضروري في هذه الحالة.ومع ذلك ، في العام, هو فقط الطريق الصحيح لتهيئة أعضاء الفئة.

إذا كان لديك منشئ مثل هذا:

X() : y(z) {
 w = 42;
}

ثم يحدث ما يلي عند X منشئ يسمى:

  • أولا جميع أعضاء يتم تهيئة:بالنسبة y, نحن نقول صراحة نتمنى أن استدعاء منشئ الذي يأخذ z كما حجتها.بالنسبة w, ماذا سيحدث يعتمد على نوع من w.إذا w قرنة نوع (التي هي في الأساس ج-متوافق مع نوع:لا الميراث ، أي منشئات أو destructors جميع أفراد العام ، وجميع أعضاء جراب أنواع كذلك) ، ثم هو لا تهيئة.القيمة الأولية مهما القمامة وجد في ذلك عنوان الذاكرة.إذا w غير جراب نوع ، ثم منشئ افتراضي يسمى (غير جراب أنواع دائما تهيئة البناء).
  • مرة واحدة كل الأعضاء وقد تم بناؤها ، ونحن ثم استدعاء عامل التعيين تعيين 42 w.

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

  • ماذا لو w هو من النوع الذي لا منشئ افتراضي?ثم هذا لن ترجمة.ثم يجب أن صراحة تهيئة بعد :, مثل y هو.
  • ما إذا كان هذا التسلسل من الدعوة سواء منشئ افتراضي و عامل التعيين هو داع بطيئة ؟ ربما سيكون أكثر كفاءة بكثير ببساطة الاتصال الصحيح منشئ لتبدأ.

لذلك باختصار ، منذ m_someMap غير جراب نوع, لا بالمعنى الدقيق للكلمة تحتاج إلى القيام به : m_someMap().كان الافتراضية التي شيدت على أي حال.ولكن إذا كان جراب نوع ، أو إذا أردنا أن ندعو آخر من منشئ افتراضي واحد ، ثم نحن بحاجة للقيام بذلك.

لمجرد أن يكون واضحا حول ما يحدث (بالنسبة إلى السؤال 2)

std::map< std::string, std::string > m_someMap يخلق كومة متغير يسمى m_someMap و منشئ افتراضي يسمى على ذلك.القاعدة C++ لجميع الكائنات هو إذا ذهبت:

T varName;

حيث T هو نوع varName الافتراضية التي شيدت.

T* varName;

يجب أن بشكل صريح تعيين إلى NULL (أو 0) - أو nullptr في المعيار الجديد.

لتوضيح القيمة الافتراضية المسألة:

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

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

عند إنشاء كائن في C++, منشئ يذهب من خلال التسلسل التالي:

  1. استدعاء المنشئات من كل من الوالدين فصول افتراضية في كل فئة شجرة (في أمر تعسفي)
  2. استدعاء منشئات جميع موروثة مباشرة الطبقات الأم في ترتيب الإعلان
  3. استدعاء المنشئات من جميع الأعضاء المتغيرات في ترتيب الإعلان

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

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

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

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