وراثت در ++C

در این جلسه از آموزش ++C به بررسی وراثت در ++C می پردازیم. یکی از مهم‌ترین مفاهیم برنامه‌نویسی شی‌گرا وراثت (inheritance) می‌باشد. وراثت اجازه می‌دهد که یک کلاس را برحسب یک کلاس دیگر تعریف کنیم، موجب آسان‌تر شدن ساخت و نگه‌داری یک برنامه می‌گردد. این مفهوم همچنین موجب استفاده مجدد از کدها و پیاده‌‌سازی سریع‌تر آنها می‌شود.

برنامه‌نویس می‌تواند هنگام نوشتن یک کلاس، به جای نوشتن داده و توابع عضو جدید، شرایطی اتخاد کند که کلاس جدید، اعضای یک کلاس از پیش موجود را به ارث ببرد. این کلاس از پیش موجود کلاس پایه (base class) نامیده می‌شود، و کلاس جدید، کلاس مشتق شده (derived class) نامیده می‌شود.

ایده وراثت یک رابطه از نوع «یک … است» (is a) می‌باشد. برای مثال، پستاندارد یک حیوان است، سگ یک پستاندار است بنابراین سگ همچنین یک حیوان است  و الی آخر.

کلاس پایه و مشتق شده

یک کلاس ممکن است از بیش از یک کلاس مشتق شده باشد، یعنی داده و توابع را از چندین کلاس پایه به ارث گرفته باشد. هنگام تعریف یک کلاس مشتق شده، از یک لیست کلاس اشتقاقی (class derivation list) برای مشخص کردن کلاس‌های پایه استفاده می‌کنیم. لیست کلاس اشتقاقی یک یا چند کلاس پایه دارای شکل زیر است.

class derived-class: access-specifier base-class

که در آن access-specifier می‌تواند public، protected یا private باشد، و base-class نام یک کلاس از پیش تعریف شده است. اگر access-specifier تعیین نشود، به صورت پیش فرض private خواهد بود.

مطلب پیشنهادی:  محصورسازی داده (Data Encapsulation) در ++C

کلاس پایه Shape و کلاس مشتق شده آن Rectangle را در مثال زیر ملاحظه کنید.

#include <iostream>
 
using namespace std;

// Base class
class Shape {
   public:
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }
      
   protected:
      int width;
      int height;
};

// Derived class
class Rectangle: public Shape {
   public:
      int getArea() { 
         return (width * height); 
      }
};

int main(void) {
   Rectangle Rect;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;
}

با اجرای کد فوق، خروجی زیر تولید می‌شود.

Total area: 35

کنترل دسترسی و وراثت

یک کلاس مشتق شده می‌تواند به همه اعضای غیرخصوصی (non-private) کلاس پایه‌اش دسترسی پیدا کند. بنابراین اعضای کلاس پایه که نباید برای توابع کلاس مشتق شده قابل دسترسی باشند را باید به صورت private اعلان کرد.

می‌توان انواع دسترسی را بر اساس «چه کسی می‌تواند دسترسی داشته باشد؟» به صورت زیر تعریف کرد.

دسترسی

public

protected

private

خود  کلاس

بله

بله

بله

کلاس‌های مشتق شده

بله

بله

خیر

کلاس‌های خارجی

بله

خیر

                  خیر

یک کلاس مشتق شده، همه متدهای کلاس پایه را به ارث می‌برد به غیراز:

  • سازنده‌ها، تخریب کننده‌ها و سازنده کپی‌های کلاس پایه
  • عملگرهای اورلود شده کلاس پایه
  • توابع دوست کلاس پایه
مطلب پیشنهادی:  آموزش کار با CMake

انواع وراثت

هنگام اشتقاق یک کلاس از یک کلاس پایه، کلاس پایه می‌تواند به صورت public، protected یا private بیان شود. نوع وراثت با access-specifierای که در بالا توضیح دادیم مشخص می‌گردد.

از وراثت نوع protected یا private به ندرت استفاده می‌شود، اما وراثت public متداول است. هنگام استفاده از انواع مختلف وراثت، قواعد زیر حاکم هستند:

  • وراثت عمومی‌: هنگام اشتقاق یک کلاس از یک کلاس پایه عمومی‌، اعضای عمومی ‌کلاس پایه به اعضای عمومی ‌کلاس مشتق شده بدل شده و اعضای محافظت شده کلاس پایه به اعضای محافظت شده کلاس مشتق شده تبدیل می‌شوند. به اعضای خصوصی یک کلاس هرگز نمی‌توان از طریق یک کلاس مشتق شده دسترسی داشت، اما می‌توان با فراخوانی اعضای عمومی ‌یا محافظت شده کلاس پایه به آنها دسترسی یافت.
  • وراثت محافظت شده: هنگام مشتق گرفتن از یک کلاس پایه محافظت شده، اعضای عمومی ‌و محافظت شده کلاس پایه به اعضای محافظت شده کلاس مشتق شده بدل می‌شوند.
  • وراثت خصوصی: هنگام مشتق گرفتن از یک کلاس پایه خصوصی، اعضای عمومی ‌و محافظت شده یک کلاس پایه به اعضای خصوصی کلاس مشتق شده تبدیل می‌شوند.

وراثت چندگانه (Multiple Inheritance)

یک کلاس ++C می‌تواند از بیش از یک کلاس اعضا را به ارث بگیرد. ساختار آن در زیر آمده است.

class derived-class: access baseA, access baseB....

در این ساختار access می‌تواند public، protected  یا private بوده که به همه کلاس‌ها تعلق می‌گیرد و این کلاس‌ها با کاما از هم جدا می‌شوند. اجازه دهید مثال زیر را با هم ملاحظه کنیم.

#include <iostream>
 
using namespace std;

// Base class Shape
class Shape {
   public:
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }
      
   protected:
      int width;
      int height;
};

// Base class PaintCost
class PaintCost {
   public:
      int getCost(int area) {
         return area * 70;
      }
};

// Derived class
class Rectangle: public Shape, public PaintCost {
   public:
      int getArea() {
         return (width * height); 
      }
};

int main(void) {
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   area = Rect.getArea();
   
   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   // Print the total cost of painting
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;

   return 0;
}

با اجرای کد فوق، خروجی زیر حاصل می‌شود

Total area: 35
Total paint cost: $2450

منبع: ترجمه از سایت tutorialspoint.com

مطلب پیشنهادی:  اعداد در ++C

امیدواریم آموزش وراثت در ++C براتون مفید واقع شده باشه. در جلسه بعدی به بررسی Overloading خواهیم پرداخت.

اگر این نوشته‌ برایتان مفید بود لطفا کامنت بنویسید.

مطالعه دیگر جلسات این آموزش<< جلسه قبلی                    جلسه بعدی >>

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *