سلسلة ++c للمحترفين الدرس 18: ما بين النسخ (Copying) والإسناد (Assignment) في Cpp


محمد الميداوي

عامل الإسناد (Assignment Operator)

يُستخدم "عامل الإسناد" لإحلال بيانات كائن ما مكان بيانات كائن موجود سلفًا (مُهيّأ مُسبقًا). انظر المثال التالي:

// عامل الإسناد
#include <iostream>
#include <string>

using std::cout;
using std::endl;

class Foo {
    public:
        Foo(int data) {
            this -> data = data;
        }~Foo() {};
    Foo & operator = (const Foo & rhs) {
        data = rhs.data;
        return *this;
    }
    int data;
};

int main() {
    Foo foo(2); // Foo(int data) استدعاء
    Foo foo2(42);
    foo = foo2; // استدعاء عامل الإسناد
    cout << foo.data << endl; //  42
}

تستطيع هنا أن تلاحظ أنّنا استدعينا عامل الإسناد بعد أن هيّئنا الكائن ‎foo‎، ثم نسند بعد ذلك ‎foo2‎ إلى ‎foo‎، وتكون جميع التغييرات التي ستحدث عند استدعاء عامل الإسناد مُعرّفة في الدالة ‎operator=‎. انظر هذا المثال الحي.

منشئ النسخ (Copy Constructor)

مُنشئ النَّسخ من ناحية أخرى على النقيض من عامل الإسناد، إذ يُستخدم لتهيئة كائن غير موجود مسبقًا (أو غير مهيّأ مسبقًا)، هذا يعني أنه ينسخ جميع البيانات من الكائن الذي يُسند إليه، دون تهيئة الكائن الذي يتم نسخه بالفعل. دعنا نلقي نظرة على نفس الشيفرة أعلاه ولكن مع استخدام مُنشئ النسخ بدلًا من منشئ الإسناد:

//منشئ النسخ     
#include <iostream>
#include <string>

using std::cout;
using std::endl;

class Foo {
    public:
        Foo(int data) {
            this -> data = data;
        }~Foo() {};
    Foo(const Foo & rhs) {
        data = rhs.data;
    }
    int data;
};

int main() {
    Foo foo(2); //Foo(int data) استدعاء
    Foo foo2 = foo; // استدعاء منشئ النسخ
    cout << foo2.data << endl;
}

في التعبير ‎Foo foo2 = foo;‎ في الدالّة الرئيسية، أسندنا الكائن على الفور قبل تهيئته، ما يعني أنه مُنشِئ نسخ، لكن لاحظ أنّنا لم نكن بحاجة إلى تمرير المعامل (int) للكائن ‎foo2‎، لأننا سحبنا البيانات السابقة تلقائيًا من الكائن foo. انظر هذا المثال الحي للمزيد.

مُنشئ النسخ مقابل منشئ الإسناد

بعد هذه النظرة السريعة على مفهومي مُنشئ النسخ ومنشئ الإسناد ورؤية مثال عن عمل كلٍ منهما، سننظر الآن كيف يمكن استخدامهما معًا في نفس الشيفرة:

// منشئ النسخ مقابل منشئ الإسناد
#include <iostream>
#include <string>

using std::cout;
using std::endl;

class Foo {
    public:
        Foo(int data) {
            this -> data = data;
        }~Foo() {};
    Foo(const Foo & rhs) {
        data = rhs.data;
    }
    Foo & operator = (const Foo & rhs) {
        data = rhs.data;
        return *this;
    }
    int data;
};

int main() {
    Foo foo(2); //Foo(int data) استدعاء المنشئ العادي
    Foo foo2 = foo; // استدعاء منشئ النسخ
    cout << foo2.data << endl;
    Foo foo3(42);
    foo3 = foo; // استدعاء منشئ الإسناد
    cout << foo3.data << endl;
}

الناتج:

2
2

لقد استدعينا في البداية مُنشئ النسخ عن طريق التعبير ‎Foo foo2 = foo;‎ لأننا لم نهيّئه من قبل، ثم استدعينا بعد ذلك عامل الإسناد على foo3 لأنه سبقت تهيئته (‎foo3=foo‎).

هذا الدرس جزء من سلسلة دروس عن C++‎.

ترجمة -بتصرّف- للفصل Chapter 29: Copying vs Assignment من كتاب C++ Notes for Professionals





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن