۹ مطلب با کلمه‌ی کلیدی «inheritance» ثبت شده است

امکانات جدید توابع مجازی

سلام!

در این جلسه می خواهیم با برخی از قابلیت های مربوط به توابع مجازی آشنا شویم. توجّه داشته باشید که قابلیت هایی که در ادامه می خوانید، در c++11 (و بعدتر) وجود دارند.

قابلیت اوّل:

کلاس های موجود در این کد را در نظر بگیرید. فعلا مشکلی در این کد دیده نمی شود؛ اما اگر تابع مجازی موجود در کلاس وارث را تغییر دهید، این تابع دیگر نسخه ی تغییر داده شده ی تابع موجود در کلاس پایه نخواهد بود.

۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی

توابع مجازی مجرد (pure virtual functions)

سلام!

در جلسات پیش با توابع مجازی آشنا شدیم. حالا می خواهیم شما را با توابع مجازی مجرد (یا pure) آشنا کنیم.

تابع مجازی مجرد، تابعی مجازی است که بدنه ندارد. برای این که به کامپایلر بگوییم که تابع مجازی مورد نظر، بدنه ندارد، باید به شکل زیر عمل کنیم؛

virtual void f( Arguments ) = 0;

۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی

تابع مخرب مجازی (virtual destructor)

سلام!

همان طور که می دانید، تابع مخرب یا destructor به طور پیش فرض در همه ی کلاس ها وجود دارد. چگونگی تغییر آن را نیز در این مطلب توضیح دادیم. حالا می خواهیم همین تابع مخرب را به صورت مجازی تعریف کنیم. برای این کار کافی است کلمه ی virtual را به اوّل اسم تابع مخرب اضافه کنیم. به عنوان مثال Prototype تابع مخرب در کلاس Test به صورت زیر خواهد بود؛

virtual ~Test();

۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی

چندریختی (polymorphism)

سلام!

در جلسه های قبل یک اشاره گر از جنس کلاس پایه ساختیم و در آن آدرس یک کلاس وارث را ذخیره کردیم. سپس متوجّه شدیم که این اشاره گر تنها توانایی دسترسی به توابع و متغّیر های خود را دارد و هیچ دسترسی ای به عضوهای کلاس وارث ندارد (با این که آدرس کلاس وارث در آن ذخیره شده است). در این جلسه می خواهیم کاری کنیم که این اشاره گر بتواند به برخی از عضوهای کلاس وارث نیز دسترسی داشته باشد.

برای این کار باید تابعی مجازی بسازیم. برای ساخت یک تابع مجازی باید کلمه ی virtual را به ابتدای Prototype آن اضافه کنید. مثلا اگر بخواهید تابعی به نام f را به صورت مجازی بسازید باید به صورت زیر عمل کنید؛

virtual void f( Arguments... );

۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی

اشاره گر و یا مرجع از نوع کلاس پایه به کلاس وارث

سلام!

در این مبحث می خواهیم یک قابلیت بسیار کاربردی را برای کلاس ها (و وراثت) آموزش دهیم. فرض کنید کدی مانند کد زیر را نوشته اید. این کد چیز خاصّی ندارد. یک کلاس Shape هست با دو وارث با نام های Square و Circle. کلاس Shape یک string دارد به نام type که در آن نوع شکل ذخیره می شود.

#include <iostream>
#include <string>
#include <cmath>

using namespace std;

class Shape{
    protected:
        string _type;
    public:
        
        Shape( string type = "Shape" ) : _type( type ) {}

        string type();

        void setType( string = "" );

        string area();

};

string Shape::type(){
    return this->_type;
}

void Shape::setType( string type ){
    this->_type = type;
}

string Shape::area(){
    return "not defined";
}

class Square : public Shape{
    protected:
        double _width;
    public:

        Square( double width = 0 ) : _width( width ) , Shape( "Square" ) {}

        double width();
        
        void setWidth( double = 0 );

        double area();
};

double Square::width(){
    return this->_width;
}

void Square::setWidth( double width ){
    this->_width = width;
}

double Square::area(){
    return pow( this->width(), 2 );
}

class Circle : public Shape{
    protected:
        double _radius;
    public:
        
        Circle( double radius = 0 ) : _radius( radius ), Shape( "Circle" ) {}

        double radius();

        void setRadius( double = 0 );

        double area();
};

double Circle::radius(){
    return this->_radius;
}

void Circle::setRadius( double radius ){
    this->_radius = radius;
}

double Circle::area(){
    return pow( this->radius(), 2) * acos( -1 );
}

int main(){
    Circle circle( 10 );
    Square square( 10 );
    Shape shape;
    cout << "I am a " << circle.type() << " and my area is " << circle.area() << endl;
    cout << "I am a " << square.type() << " and my area is " << square.area() << endl;
    cout << "I am a " << shape.type() << " and my area is " << shape.area() << endl;
    return 0;
}

حالا یک اشاره گر با نوع کلاس Shape می سازیم و آدرس آن را برابر با آدرس یک Object از Square قرار می دهیم، یعنی

Shape *shape = &square;

۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی

ارث بری چند گانه (Multiple Inheritance)

سلام!

در جلسات قبل با مفهوم ارث بری آشنا شدیم. حالا می خواهیم با مفهوم ارث بری چند گانه آشنا شویم.

یک هاورکرافت را در نظر بگیرید. این وسیله هم یک وسیله ی نقلیه ی زمینی است و هم یک وسیله ی نقلیه ی آبی. پس ویژگی های این دو را به ارث می برد. در واقع دو کلاس پایه برای هاورکرافت وجود دارد. کد آن شبیه کد زیر می شود؛

class HoverCraft : public LandVehicle , public WaterVehicle;
۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی

تغییر عضوهای کلاس پایه از طریق کلاس وارث

سلام!

در این جلسه می خواهیم توابع موجود در کلاس پایه و سطح دسترسی به عضوهای کلاس پایه را تغییر دهیم.

فرض کنید در کلاس پایه ی خود یک تابع به نام test دارید و در کلاس وارث چنین تابعی ندارید. اگر در برنامه ی خود بنویسید

Derived_Obj.test();

کامپایلر ابتدا در خود کلاس وارث دنبال تابع test می گردد و اگر پیدا نکند، در زنجیره ی ارث بری به سمت بالا حرکت می کند تا چنین تابعی را پیدا کند. حالا کد زیر را در نظر بگیرید. همان طور که می بینید، تابع identify را چه با کلاس پایه و چه با کلاس وارث صدا بزنیم، یک تابع صدا زده می شود و آن هم تابع identify در کلاس پایه است.

#include <iostream>

using namespace std;

class Base{
    protected:
        
        int foo;
    
    public:
        
        Base( int value = 0 ) : foo( value ) {}
        
        void identify();
        
};

void Base::identify(){
    cout << "Base!\n";
}

class Derived : public Base{
    public:
        
        Derived( int value = 0 ) : Base( value ) {}
        
};

int main(){
    Base base;
    base.identify();
    
    Derived derived;
    derived.identify();
}

این نکته که بدیهی بود، حالا می خواهیم این تابع را تغییر دهیم.

۰ نظر موافقین ۰ مخالفین ۰
روزبه صیادی