سؤال

أنا أعرف أن المترجم في بعض الأحيان يوفر الافتراضي نسخ منشئ إذا لم تنفذ نفسك.أنا في حيرة حول ما بالضبط هذا المنشئ لا.إذا كان لدي فئة التي تحتوي على كائنات أخرى ، ولم المعلن نسخ منشئ, ماذا سيكون سلوك ؟ على سبيل المثال, فئة مثل هذا:

class Foo {
  Bar bar;
};

class Bar {
  int i;
  Baz baz;
};

class Baz {
  int j;
};

الآن إذا كنت تفعل هذا:

Foo f1;
Foo f2(f1);

ما الافتراضي نسخ منشئ تفعل ؟ سوف مترجم إنشاء نسخ منشئ في Foo استدعاء مترجم إنشاء منشئ في Bar أن أكثر من نسخة bar, والتي سوف ثم استدعاء مترجم إنشاء نسخ منشئ في Baz?

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

المحلول

Foo f1;
Foo f2(f1);

نعم هذا ما كنت تتوقع أن:
F2 نسخ منشئ فو::فو(فو const&) يسمى.
هذه النسخة يبني قاعدة الطبقة ومن ثم كل عضو (بشكل متكرر)

إذا قمت بتعريف فئة مثل هذا:

class X: public Y
{
    private:
        int     m_a;
        char*   m_b;
        Z       m_c;
};

الطرق التالية سوف يتم تحديدها من قبل المترجم الخاص بك.

  • منشئ (افتراضي) (2 الإصدارات)
  • منشئ (نسخ)
  • المدمر (الافتراضي)
  • عامل التعيين

المنشئ:الافتراضي:

هناك بالفعل اثنين من الافتراضي المنشئات.
واحد يستخدم zero-initialization في حين أن الآخر هو استخدام value-initialization.المستخدمة يعتمد على ما إذا كنت تستخدم () أثناء التهيئة أو لا.

// Zero-Initialization compiler generated constructor
X::X()
    :Y()                // Calls the base constructor
                        //     If this is compiler generated use 
                        //     the `Zero-Initialization version'
    ,m_a(0)             // Default construction of basic PODS zeros them
    ,m_b(0)             // 
    m_c()               // Calls the default constructor of Z
                        //     If this is compiler generated use 
                        //     the `Zero-Initialization version'
{
}

// Value-Initialization compiler generated constructor
X::X()
    :Y()                // Calls the base constructor
                        //     If this is compiler generated use 
                        //     the `Value-Initialization version'
    //,m_a()            // Default construction of basic PODS does nothing
    //,m_b()            // The values are un-initialized.
    m_c()               // Calls the default constructor of Z
                        //     If this is compiler generated use 
                        //     the `Value-Initialization version'
{
}

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

منشئ (نسخ)

X::X(X const& copy)
    :Y(copy)            // Calls the base copy constructor
    ,m_a(copy.m_a)      // Calls each members copy constructor
    ,m_b(copy.m_b)
    ,m_c(copy.m_c)
{}

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

عامل التعيين

X& operator=(X const& copy)
{
    Y::operator=(copy); // Calls the base assignment operator
    m_a = copy.m_a;     // Calls each members assignment operator
    m_b = copy.m_b;
    m_c = copy.m_c;

    return *this;
}

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

المدمر

X::~X()
{
                        // First runs the destructor code
}
    // This is psudo code.
    // But the equiv of this code happens in every destructor
    m_c.~Z();           // Calls the destructor for each member
    // m_b              // PODs and pointers destructors do nothing
    // m_a          
    ~Y();               // Call the base class destructor
  • إذا أي منشئ (بما في ذلك نسخ) وأعلن ثم منشئ افتراضي لا يتم تنفيذه من قبل المترجم.
  • إذا كان منشئ نسخة وأعلن ثم المترجم لا تولد واحدة.
  • إذا كان عامل التعيين وأعلن ثم المترجم لا تولد واحدة.
  • إذا المدمر أعلن المترجم لا تولد واحدة.

ابحث في التعليمات البرمجية التالية نسخ المنشئات يتم إنشاؤها:

Foo::Foo(Foo const& copy)
    :bar(copy.bar)
{}

Bar::Bar(Bar const& copy)
    :i(copy.i)
    ,baz(copy.baz)
{}

Baz::Baz(Baz const& copy)
    :j(copy.j)
{}

نصائح أخرى

والمترجم يوفر منشئ نسخة إلا إذا كنت <م> أعلن (ملاحظة: لا <م> تحديد ) واحد نفسك. نسخة منشئ ولدت مترجم تدعو ببساطة منشئ نسخة من كل عضو من أعضاء فئة (ولكل فئة أساسية).

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

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

ووC ++ نسخة منشئ افتراضي يخلق <ل أ href = "http://fredosaurus.com/notes-cpp/oop-condestructors/shallowdeepcopy.html" يختلط = "نوفولو noreferrer"> نسخة الضحلة. وهناك نسخة ضحلة لا يخلق نسخ جديدة من الكائنات التي قد تشير الكائن الأصلي الخاص بك؛ سوف الكائنات القديمة والجديدة تحتوي على مجرد مؤشرات واضحة إلى نفس موقع الذاكرة.

والمترجم سيولد المنشئات اللازمة للك.

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

وعن طريق المثال الخاص بك:

class Baz {
    Baz(const Baz& b) {}
    int j;
};
class Bar {
    int i;
    Baz baz;
};
class Foo {
    Bar bar;
};

ومحاولة الافتراضي مثيل أو نسخ بناء فو سوف يرمي خطأ منذ باز لا نسخ constructable والمترجم لا يمكن إنشاء الافتراضي ونسخ constroctor لفو.

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