Programming Basics SQL HTML CSS JavaScript Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Learn Typing

C++منع إمكانية إعادة تعريف الدوال

  • الكلمة final
  • أمثلة شاملة على الكلمة final

الكلمة final

إذا كنت تريد منع الكلاس الإبن من إعادة تعريف الدالة التي ورثها من الكلاس فيمكنك جعل نوع الدالة virtual final حتى أنه يمكنك جعل نوع الكلاس بأكمله final لا يمكن إعادة تعريف أي دالة موجودة فيه بهدف أن يتم استخدام الدوال الموجودة فيه كما هي.

ملاحظة: تم إضافة هذه الكلمة إبتداءاً من الإصدار C++ 11 و الإصدارات اللاحقة.


مصطلحات تقنية

  • الدالة التي لا يمكن إعادة تعريفها يقال لها في العادة دالة ثابتة.
  • الكلاس الذي لا يمكن إعادة تعريف أي شيء موجود فيه يقال له كلاس ثابت.


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

الكلمة final يمكن استخدامها كإسم لمتغير, دالة, مصفوفة, كائن إلخ.. لأنها لا تعتبر من الكلمات المحجوزة ( Keywords ) في اللغة.

أمثلة شاملة على الكلمة final


في المثال التالي قمنا بتعريف كلاس إسمه Base يحتوي على دالة ثابتة إسمها func().
بعدها قمنا بتعريف كلاس إسمه Derived يرث من الكلاس Base و حاولنا فيه إعادة تعريف الدالة func() لتنبيهك من الخطأ الذي قد يظهر في حال حاولت إعادة تعريف دالة ثابتة في الكلاس الذي يرثها.

المثال الأول

main.cpp
#include <iostream>
using namespace std;
// func يحتوي على دالة ثابتة إسمها Base هنا قمنا بتعريف كلاس إسمه
class Base
{
public:
virtual void func() final
{
cout << "Base class default behaviour \n";
}
};
// func و فيه قمنا بإعادة تعريف الدالة الثابتة Base يرث من الكلاس Derived هنا قمنا بتعريف محتوى الكلاس
class Derived : public Base
{
public:
void func() override // هذا السطر الذي سيسبب المشكلة عند التشغيل
{
cout << "Derived class overridden behaviour \n";
}
};
// main() هنا قمنا بتعريف الدالة
int main()
{
return 0;
}
#include <iostream> using namespace std; // func يحتوي على دالة ثابتة إسمها Base هنا قمنا بتعريف كلاس إسمه class Base { public: virtual void func() final { cout << "Base class default behaviour \n"; } }; // func و فيه قمنا بإعادة تعريف الدالة الثابتة Base يرث من الكلاس Derived هنا قمنا بتعريف محتوى الكلاس class Derived : public Base { public: void func() override // هذا السطر الذي سيسبب المشكلة عند التشغيل { cout << "Derived class overridden behaviour \n"; } }; // main() هنا قمنا بتعريف الدالة int main() { return 0; }

سيظهر الخطأ التالي عند التشغيل.

error: virtual function 'virtual void Derived::func()' overriding final function
    note: overridden function is 'virtual void Base::func()'
        In member function 'virtual void Derived::func()'

في المثال السابق حدث الخطأ فعلياً بسبب السطر 19 حيث أن المترجم قال بأنه لا يمكن إعادة تعريف الدالة func() في الكلاس Derived الذي ورثها لأنها في الكلاس الأب Base معرّفة كدالة ثابتة.



في المثال التالي قمنا بتعريف كلاس ثابت إسمه Base يحتوي على دالة إسمها func().
بعدها قمنا بتعريف كلاس إسمه Derived يرث من الكلاس Base فقط لتنبيهك من الخطأ الذي قد يظهر في حال حاولت الوراثة من كلاس ثابت.

المثال الثاني

main.cpp
#include <iostream>
using namespace std;
// func يحتوي على دالة إسمها Base هنا قمنا بتعريف كلاس ثابت إسمه
class Base final
{
public:
void func()
{
cout << "Base class default behaviour \n";
}
};
// و طبعاً هذا الأمر سيسبب مشكلة عند التشغيل Base يرث من الكلاس Derived هنا قمنا بتعريف محتوى الكلاس
class Derived : public Base
{
};
// main() هنا قمنا بتعريف الدالة
int main()
{
return 0;
}
#include <iostream> using namespace std; // func يحتوي على دالة إسمها Base هنا قمنا بتعريف كلاس ثابت إسمه class Base final { public: void func() { cout << "Base class default behaviour \n"; } }; // و طبعاً هذا الأمر سيسبب مشكلة عند التشغيل Base يرث من الكلاس Derived هنا قمنا بتعريف محتوى الكلاس class Derived : public Base { }; // main() هنا قمنا بتعريف الدالة int main() { return 0; }

سيظهر الخطأ التالي عند التشغيل.

error: cannot derive from 'final' base 'Base' in derived type 'Derived'

في المثال السابق حدث الخطأ فعلياً بسبب السطر 16 حيث أن المترجم قال بأنه لا يمكن الوراثة من الكلاس Base لأنه كلاس ثابت.



في المثال التالي قمنا بتعريف كلاس ثابت إسمه Base يحتوي على دالة إسمها func().
بعدها قمنا بإنشاء كائن منه و استدعاء الدالة الموجودة فيه.

المثال الثالث

main.cpp
#include <iostream>
using namespace std;
// func يحتوي على دالة إسمها Base هنا قمنا بتعريف كلاس ثابت إسمه
class Base final
{
public:
void func()
{
cout << "Base class default behaviour \n";
}
};
// main() هنا قمنا بتعريف الدالة
int main()
{
// b إسمه Base هنا قمنا بإنشاء كائن من الكلاس
Base b;
// b من الكائن func() هنا قمنا باستدعاء الدالة
b.func();
return 0;
}
#include <iostream> using namespace std; // func يحتوي على دالة إسمها Base هنا قمنا بتعريف كلاس ثابت إسمه class Base final { public: void func() { cout << "Base class default behaviour \n"; } }; // main() هنا قمنا بتعريف الدالة int main() { // b إسمه Base هنا قمنا بإنشاء كائن من الكلاس Base b; // b من الكائن func() هنا قمنا باستدعاء الدالة b.func(); return 0; }

سنحصل على النتيجة التالية عند التشغيل.

Base class default behaviour