سازنده ها و مخرب ها در وراثت
کلاس پايه و مشتق شده هر يک می تواند شامل توابع سازنده و مشتق شده باشند. وقتی شیئی ايجاد می شود کامپايلر تضمين می کند که کليه سازنده ها فراخوانی می شوند. در سلسله مراتب وراثت فراخوانی سازنده ها از ريشه شروع می شود. در هر سطح ابتدا سازنده کلاس پايه سپس سازنده کلاس مشتق شده فراخوانی می شود. مخرب ها برعکس ترتيب فراخوانی سازنده ها فراخوانی می شوند.
مثال. در برنامه زير کلاس Derived2 از کلاس Derived1 که خود از Base1 ارث بری دارد ارث می برد.
#include <iostream.h>
class Base1 {
int x;
public:
Base1 () {cout << "Base1 constructorn";}
~Base1() {cout << "Base1 destructorn";}
};
class Derived1 : public Base1 {
int y;
public:
Derived1() { cout << "Derived1 constructorn";}
~Derived1() { cout << "Derived1 destructorn";}
};
class Derived2 : public Derived1 {
int z;
public:
Derived2() { cout << "Derived2 constructorn";}
~Derived2() { cout << "Derived2 destructorn";}
};
int main() {
Derived2 d2;
return 0;
}
خروجی برنامه به صورت زير است:
Base1 constructor
Derived1 constructor
Derived2 constructor
Derived2 destructor
Derived1 destructor
Base1 destructor
نکته. ترتيب فراخوانی سازنده ها و مخرب ها در در توارث چندگانه هم صدق می کند. سازنده ها به ترتيبی که در ليست مشخص شده اند از چپ به راست فراخوانی می شوند. و مخرب ها برعکس.
ارسال پارامتر به سازنده کلاس پايه
زمانی که تنها سازنده کلاس مشتق شده دارای آرگومان است می توان به سادگی و به صورت متعارف آرگومان را به سازنده ارسال نمود. اما برای ارسال آرگومان به سازنده کلاس پايه دچار مشکل می شويد چون سازنده کلاس مشتق شده به داده خصوصی کلاس پايه دسترسی ندارد و نمی تواند آنها را مقداردهی کند. برای اين کار C++ گرامری را در اختيار می گذارد که ليست مقداردهی سازنده (constructor initializer list) نام دارد. ليست مقداردهی سازنده امکان فراخوانی صريح سازنده ها از اشيای عضو را می دهد. فرم کلی آن برای سازنده کلاس مشتق شده به صورت زير است:
Derived(arg_list) : Base1(arg_list), Base2(arg_list), ...
{ //body of derived constructor}
نام کلاس های پايه توسط کاما از هم جدا می شوند. Base1 و Base2 و ... نام کلاس های پايه هستند که توسط کلاس مشتق شده Derived به ارث برده می شوند. سازنده ها همگی قبل از اينکه وارد بدنه سازنده کلاس مشتق شده شويد فراخوانی می شوند.
مثال. کلاس Circle از کلاس Point مشتق شده است. در سازنده کلاس Circle سازنده Coint فراخوانی می شود.
#include <iostream.h>
class Point {
int x,y;
public:
Point(int atx,int aty ) {x = atx; y = aty;}
~Point(){ cout << "Point Destructor calledn";}
virtual void Draw() { cout << "Draw point at " << x << " " << y << endl;}
};
class Circle : public Point {
int radius;
public:
Circle(int atx, int aty, int theRadius) ;
~Circle() ;
virtual void Draw() ;
};
Circle::Circle(int atx,int aty,int theRadius) : Point(atx,aty) {
radius = theRadius;
}
inline Circle::~Circle() {
cout << "Circle Destructor called" << endl;
}
void Circle::Draw( void ) {
Point::Draw();
cout << "circle::Draw point " << " Radius " << radius << endl;
}
int main() {
Circle ACircle(10,10,5) ;
ACircle.Draw();
return 0;
}
برخلاف اينکه اغلب نياز است سازنده ها به صورت مستقيم در ليست مقداردهی فراخوانی شوند، مخرب ها نيازی به فراخوانی صريح ندارند زيرا هر کلاس تنها يک مخرب بدون هيچ آرگومانی دارد. کامپايلر کليه مخرب ها را از آخرين کلاس مشتق شده به سمت ريشه در کل سلسله مراتب وارثت اجرا می کند.