نسخة ضحلة ونسخة عميقة
في فئة الدائرة، تم شرح مثال مُنشئ النسخ في القسم السابق، وتتوافق استراتيجية النسخ مع الإستراتيجية الافتراضية للنظام، أي يتم نسخ أعضاء الكائن الأصلي إلى الأعضاء المقابلين للكائن الجديد بالتسلسل. في هذه الحالة، لماذا مازلنا هل تريد تعريفها بنفسك؟ والسبب هو أن مجرد تهيئة جميع المواقف بهذه الطريقة البسيطة سيؤدي حتمًا إلى مشاكل في مواقف مختلفة.
على سبيل المثال، في فئة الدائرة الآن، إذا تمت إضافة عضو مؤشر إلى متغير العضو وتحتاج الذاكرة إلى تخصيصها ديناميكيًا أثناء التهيئة، فسيكون هناك خطر أمني كبير، ويكون الرمز كما يلي:
/***************************: // حقوق الطبع والنشر: www.dotcpp.com//التاريخ:2017/8/26****************************** ** ******/#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);~Circle(); );doublegirth();};Circle::~Circle(){delete[]str;}Circle::Circle(doubleR,char*str){cout<<Constructor<<endl;this->R=R ;هذا ->str=newchar[strlen(str)+1];strcpy(this->str,str);cout<<this->R<<<<this->str<<endl;}doubleCircle::area () {returnPI*R*R;}doubleCircle::girth(){return2*PI*R;}intmain(){CircleA(5,NO.1Oldclass);CircleB(A);return0;}
للتحقق، في فئة الدائرة، أضفنا عضو مؤشر وقمنا بتهيئته في المُنشئ بدون مُنشئ نسخة مخصص. ثم في الوظيفة الرئيسية، تقوم الجملة Circle B(A); بتعيين الكائن A إلى الكائن B، واستدعاء مُنشئ النسخة الافتراضية بعد التشغيل، يُبلغ البرنامج عن خطأ كما هو موضح أدناه:
السبب الفعلي هو أن مُنشئ النسخ الافتراضي يقوم فقط بتعيين البيانات ولا يمكنه فتح مساحة الذاكرة للمؤشرات، وهو ما يعادل الكود:
هذا->str=str;
لذا، يشير المؤشران بشكل أساسي إلى جزء من مساحة الكومة. لقد ذهب ضد نيتنا الأصلية. ثم في نهاية البرنامج، عند إعادة تدوير الكائنين، سيتم استدعاء أدوات التدمير الخاصة بهما لتحرير مساحة الذاكرة هذه، نظرًا لأنه يجب استدعاء الكائنين مرتين، أي حذفهما مرتين، سيحدث خطأ!
لذلك، عندما يكون هناك نوع مؤشر في الفصل، فإن الاعتماد على طريقة مُنشئ النسخ الافتراضية لم يعد قادرًا على تلبية احتياجاتنا، ويجب تحديد مُنشئ نسخة محدد، والذي لا يمكنه نسخ البيانات فحسب، بل يمكنه أيضًا تخصيص مساحة الذاكرة للأعضاء. لتحقيق نسخة حقيقية، وتسمى أيضًا النسخة العميقة، هذا هو مُنشئ النسخة العميقة .
تنفيذ مُنشئ النسخة العميقة:
#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);Circle(Circle&A);~Circle();doublerea(); doublegirth();};Circle::~Circle(){delete[]str;cout<<CallDestructor<<endl;}Circle::Circle(Circle&A){cout<<CopyConstructor<<endl;this->R=AR ;this->str=newchar[strlen(A.str)+1];strcpy(this->str,A.str);}Circle::Circle(doubleR,char*str){cout<<Constructor<<endl ;this->R=R;this->str=newchar[strlen(str)+1];strcpy(this->str,str);}doubleCircle::area(){returnPI*R*R;}doubleCircle: :مقاس(){return2*PI*R;}intmain(){CircleA(5,NO.1Oldclass);CircleB(A);return0;}
مبدأ التنفيذ مشابه للمنشئ مع فتح مساحة ذاكرة كافية قبل التعيين لإكمال النسخة الكاملة، وهذا ما يسمى بـ "النسخة العميقة". يرجى فهم وتجربته على الكمبيوتر!