اذهب إلى المحتوى

ما بين النسخ (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


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

أفضل التعليقات

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



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...