منوی سریع

آموزش برنامه نویسی C++ تعریف کلاس و تابع سازنده و اشاره گر به کلاس و اشیاء کلاس ها (Classes) و اشیا (Objects) در برنامه نویسی C++ :

اکنون وقت آن است که برنامه نویسی شی گرا را در عمل یاد گرفته و با اصول تعریف و بکارگیری آن بیشتر آشنا بشویم .

  • کلاس ها (Classes) :

کلاس ها همان نوع داده تجریدی یا انتزاعی (Abstract) هستند. به عبارتی یک نوع داده هستند که توسط برنامه نویس برای کار با داده ها و توابع و رویدادهای مختلفی تعریف می شوند. برای تعریف کلاس از الگوی زیر پیروی می کنیم :


1
2
3
4
5
6
7
8
9
10
class className
{
    // Define private variables & functions
    public:
        // Define public variables & functions
    private:
        // Define private variables & functions
    protected:
        // Define protected variables & functions
} objectsame;   // Declare Objects

همانطور که در بالا آمد، برای تعریف یک کلاس از کلمه کلیدی class استفاده می کنیم و نامی را در ادامه برای آن تعیین می کنیم .

متغیرها و توابع مربوط به class در درون بلوک آکولاد قرار خواهند گرفت. فرض بر این است که دسترسی داده ها و توابع private است مگر اینکه نوع دسترسی صراحتا اعلام شود .

داده ها و توابعی که طبق سطر 3 تعریف شوند بطور پیش فرض از سطح دسترسی private برخوردار خواهند بود زیرا چیزی برای آنها تعریف نشده است کما اینکه در سطر 6 این سطح دسترسی کاملا بیان شده است .

سطح دسترسی private به این معناست که که داده ها و توابع تعریفی در این سطح، فقط در این class شناخته می شوند و در خارج از کلاس هیچگونه دسترسی به آنها وجود ندارد و تمامی عملیات روی آنها فقط باید در همان class تعریف شوند که همان مفهوم Encapsulation یا محرمانگی و بسته بندی را پیاده سازی می کنند .

در سطر 4 می توان داده ها و توابعی را که دارای سطح دسترسی public یا عمومی هستند را تعریف نمود و این بدین معناست که داده ها و توابع با این سطح دسترسی هم در داخل و هم در خارج از class قابل دسترسی هستند .

در سطر 8 نیز نوع دسترسی protected ذکر شده، یعنی کلاس هایی که از این کلاس به ارث برده می شنود می توانند به این قسم از داده ها و توابع دسترسی داشته باشند .

در سطر 10 و در خارج از محدوده کلاس نیز باید اشیائی را برای دسترسی به اعضای class خود ایجاد نماییم که به ذکر نام یا نام هایی که با کاما از هم جدا می شوند بسنده می کنیم. دقت داشته باشید که ایجاد شی از کلاس را می توان در درون تابع main نیز انجام داد .

در ادامه شاهد تعریفی از یک کلاس خواهیم بود :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream.h>
#include <conio.h>

class CRectangle
{
        int x,y;
    public:
        void set_Values(int, int);
        int area() { return (x*y);}
} obj_1;

void CRectangle :: set_Values(int a, int b)
{
    x = a;
    y = b;
}

void main()
{
    obj_1.set_Values(3,4);
    CRectangle obj_2;
    obj_2.set_Values(5,6);
    cout << "area = " << obj_1.area() << "\n";
    cout << "area = " << obj_2.area();
    getch();
}
area = 12
area = 30

در کد C++ بالا شاهد تعریف جامعی از یک class هستیم .

کلاس CRectangle در سطر 4 از برنامه تعریف شده و بدنه تعریف آن تا انتهای سطر 10 ادامه میابد. دو متغیر به نامهای x,y برای این کلاس تعریف شده است. چون هیچ سطح دسترسی برای آن دو مشخص نگردیده کامپایلر آنها را پیش فرض private تعیین می نماید یعنی فقط اعضای این class می توانند به آن دو دسترسی داشته باشند .

دو تابع با نامهای set_Values() و area() برای این class تعریف شده که یکی وظیفه دریافت مقادیر و دیگری محاسبه مساحت را بر عهده دارند .

عملکرد تابع set_Values() در بیرون از class و از سطر 12 الی 16 تعریف شده است، اما دستورات تایع area() در درون خود class بیان شده است که از هر یک از این دو روش برای تعریف دستورات و عملکرد توابع می شود استفاده نمود .

آموزش برنامه نویسی C++ تعریف کلاس و تابع سازنده و اشاره گر به کلاس و شی و اشیاء نکته) در سطر 12 به نحوه تعریف تابع در خارج از class دقت کنید که ابتدا نوع بازگشتی تابع وسپس نام class و بعد از آن از علامت :: و در نهایت نام تابع و آرگومانهای آن را بیان می کنیم .

در سطر 9 هم چنانچه مشاهده می کنید در همان محل تعریف تابع area() ، دستورات را هم برای تابع نوشته ایم .

برای کلاس CRectangle دو شی یا object ایجاد شده که یکی در سطر 10 و دقیقا بعد از تعریف class، و دیگری در تابع main در سطر 21. دقت کنید که برای ایجاد شی از کلاس در درون بدنه برنامه باید ابتدا نام کلاس و سپس نام شی را بیان نمایید .

هیچ یک از این دو شی ربطی به هم ندارند و هر یک به طور جداگانه از اعضای کلاس استفاده می کنند .

برای دسترسی به اعضای کلاس با استفاده از شی، ابتدا نام کلاس سپس نقطه و در انتها نام عضو که می تواند یک متغیر یا یک تابع یا یک رخداد باشد را ذکر می کنیم، دقت داشته باشید که اگر عضو مورد نظر دارای سطح دسترسی private باشد نمی توان به آن دسترسی داشت زیرا فقط در درون کلاس شناخته شده است و در بیرون از کلاس خود حتی با استفاده از ایجاد شی هم نمیتوان با آنها کار کرد. به کد زیر توجه کنید :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class CRectangle
{
     
        int x;
    public:
        void f1();
        void f2() ;
        int y;
    private:
        void f3();
        int z;
        
} obj_1;

void main()
{
    obj_1.x;      // ERROR - x is private
    obj_1.y;      // OK    - y is public
    obj_1.f1();   // OK    - f1 is public
    obj_1.f2();   // OK    - f2 is public
    obj_1.f3();   // ERROR - f3 is private
    obj_1.z;      // ERROR - z is private
}

فکر کنم که توضیحات در کد گویای همه چیز باشد .

آموزش برنامه نویسی C++ تعریف کلاس و تابع سازنده و اشاره گر به کلاس و اشیاء تابع سازنده کلاس (Constructor) :

همانطور که مشاهده کردید در کلاس بالا تابع set_Values() وظیفه مقدار دادن به متغیر ها که همان عرض و طول یک چهار ضلعی هستند را بر عهده داشت. اما در کلاس تابعی بنام سازنده کلاس وجود دارد که کار مقداردهی اولیه به متغیرهای لازم را انجام می دهد .

تابع سازنده، تابع عضو ویژه ای است هم نام با نام کلاس که نوع بازگشتی ندارد و حتی از نوع void هم نیست اما می تواند پارامتر ورودی داشته باشد و دارای دسترسی public می باشد .

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

آموزش برنامه نویسی C++ تعریف کلاس و تابع مخرب و اشاره گر به کلاس و اشیاء تابع مخرب کلاس (Destructor) :

وقتی که کار با شی مورد نظر تمام شد بهتر است که فضایی را که در حافظه به متغیرهای عضو کلاس توسط تابع سازنده یا مولد داده شده است را آزاد کنیم که اینکار را با استفاده از تابع عضو ویژه دیگری بنام تابع مخرب انجام می دهیم. این تابع نیز دارای ویژگیهای تعریفی تابع سازنده است با این تفاوت که با علامت ~ در ابتدای آن تعریف می گردد .

در ادامه به نحوه تعریف و استفاده از توابع عضو سازنده و مخرب در کلاس می پردازیم :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream.h>
#include <conio.h>

class CRectangle
{
        int *width, *heigth;
    public:
        CRectangle(int, int);
        ~CRectangle();
        int area() { return (*width * *heigth);}
};

CRectangle :: CRectangle(int a, int b)
{
    width = new int;
    heigth = new int;
    *width = a;
    *heigth = b;
}

CRectangle :: ~CRectangle()
{
    delete width;
    delete heigth;
}

void main()
{
    CRectangle rect1(3,4), rect2(5,6);
    cout << "rect1 area = " << rect1.area() << "\n";
    cout << "rect2 area = " << rect2.area();
    getch();
}
rect1 area = 12
rect2 area = 30

خوب، تابع مولد (سازنده) کلاس در سطر 8 از برنامه و تابع مخرب کلاس هم در سطر بعدی تعریف شده اند. سطرهای 13 تا 25 نحوه رفتار این دو تابع عضو کلاس را بیان می کنند. دقت فرمایید که دو متغیر عضو کلاس از نوع اشاره گر تعریف شده اند، پس برای کار با آنها در تابع سازنده کلاس باید متغیرهایی از نوع اشاره گر داشته باشیم که این کار را در سطرهای 15و16 انجام داده ایم .

با استفاده از کلمه کلیدی new می توان یک object یا همان شی را تعریف نماییم. یک شی این قابلیت را دارد که هر نوعی را بگیرد (این را از مفهوم شی گرایی درک کردیم!). پس بعد از تعریف شی های width, height آنها را اشاره گر در نظر میگیریم (سطرهای 17و18) .

کلمه کلیدی delete که در سطرهای 23و24 بکار رفته است دستوری است برای آزادسازی حافظه اشغالی توسط هر شی یا متغیر ، ... در برنامه .

ادامه برنامه کاملا واضح است .

آموزش برنامه نویسی C++ تعریف کلاس و تابع سازنده و مخرب اشاره گر به کلاس و اشیاء و سربارگزاری توابع عضو کلاس سربارگذاری توابع عضو کلاس در برنامه نویسی C++ (Overloading Constructors) :

مانند سربارگذاری توابع، سازنده های کلاس را نیز میتوان با نامهای مشابه ولی با آرگومانهای متفاوت سربار نمود که در زیر نمونه ای را به همراه هم خواهیم دید :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream.h>
#include <conio.h>

class CRectangle
{
        int width,heigth;
    public:
        CRectangle();
        CRectangle(int, int);
        int area(void) { return (width*heigth);}
};

CRectangle :: CRectangle()
{
    width = 5;
    heigth = 5;
}

CRectangle :: CRectangle(int a, int b)
{
    width = a;
    heigth = b;
}

void main()
{
    CRectangle rect1(3,4);
    CRectangle rect2;
    cout << "rect1 area = " << rect1.area() << "\n";
    cout << "rect2 area = " << rect2.area();
    getch();
}
rect1 area = 12
rect2 area = 25

نکته) به سطر 28 توجه نمایید که دیگر از پرانتز باز و بسته استفاده نمی کنیم و در صورت استفاده، کامپایلر از برنامه خطا خواهد گرفت (برخلاف سربارگذاری در توابع) .

آموزش برنامه نویسی C++ تعریف کلاس و تابع سازنده و اشاره گر به کلاس و اشیاء تابع سازنده پیش فرض (Default constructor) :

هنگامی که برای یک کلاس تابع سازنده ای تعریف نکنیم، کامپایلر بطور پیش فرض، فرض می کند که کلاس سازنده ای دارد اما بدون پارامتر. به همین دلیل است که وقتی کلاسی بدون تابع سازنده را تعریف می کنیم می توانیم از آن یک شی ایجاد کنیم که کار تعریف تابع سازنده را خود کامپایلر انجام میدهد .


1
2
3
4
5
6
7
8
class CExample
{
    public:
        int a, b, c;
        void multiply (int n, int m) { a=n; b=m; c=a*b; }
};

CExample ex;

همانطور که در کد برنامه نویسی C++ بالا می بینیم برای کلاس هیچگونه تابع سازنده ای تعریف نشده اما میتوان از کلاس CExample یک شی بنام ex ایجاد نمود و در طول برنامه از آن استفاده کرد و تنها دلیل این موضوع فرض کامپایلر بر وجود یک تابع سازنده بدون پارامتر در کلاس است .

اما اگر خود برای کلاس تابع سازنده ای را تعریف کنیم دیگر کامپایلر فرضی را در نظر نگرفته و بر مبنای تابع سازنده تعریفی ما عمل خواهد کرد مانند کد زیر :


1
2
3
4
5
6
7
8
9
10
class CExample
{
    public:
        int a, b, c;
        CExample (int n, int m) { a=n; b=m; };
        void multiply () { c=a*b; };
};

CExample ex;         //نادرست
CExample ex(2,8);    //درست

در کد برنامه نویسی C++ بالا ما برای کلاس CExample که دارای یک تابع سازنده تعریفی توسط ما با 2 پارامتر ورودی است 2 شی تعریف کرده ایم. دستور ایجاد شی در سطر 9 نادرست است زیرا تابع سازنده این کلاس دارای 2 پارامتر است که در سطر 5 تعریف شده و در حین ایجاد شی از کلاس باید مقداردهی شوند و دیگر کامپایلر مبنا را فرض خود در نظر نمی گیرد و بر اساس کد ما عمل می نماید .

آموزش برنامه نویسی C++ تعریف کلاس و تابع سازنده و اشاره گر به کلاس و اشیاء اشاره گر به کلاس (Pointers to Classes) :

اشاره گرها همانطور که می توانند به متغیرها اشاره کنند، می توانند به اشیاء یک کلاس نیز اشاره کنند و چون شی نمونه ای از کلاس است پس به کلاس اشاره می کنند .

در حالت ساده برای دسترسی به اعضای کلاس توسط شی تعریفی، از نقطه (.) استفاده کردیم. اما در اشاره گر به شی باید از ترکیب 2 کاراکتر خط و بزرگتر (<-) استفاده کنیم. با هم مثالی کامل از اشاره گر به شی یا همان کلاس را بررسی می کنیم :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream.h>
#include <conio.h>

class CRectangle
{
    int width, height;
  public:
    void set_values (int, int);
    int area (void) {return (width * height);}
};

void CRectangle::set_values (int a, int b)
{
  width = a;
  height = b;
}

int main()
{
  CRectangle a, *b, *c;
  CRectangle * d = new CRectangle[2];
  b= new CRectangle;
  c= &a;
  a.set_values (1,2);
  b->set_values (3,4);
  d->set_values (5,6);
  d[1].set_values (7,8);
  cout << "a area: " << a.area() << endl;
  cout << "*b area: " << b->area() << endl;
  cout << "*c area: " << c->area() << endl;
  cout << "d[0] area: " << d[0].area() << endl;
  cout << "d[1] area: " << d[1].area() << endl;
  delete[] d;
  delete b;
  return 0;
}
a area: 2
*b area: 12
*c area: 2
d[0] area: 30
d[1] area: 56

همانطور که می بینید در قطعه کد برنامه نویسی C++ در خطوط 4 الی 10 تابعی با نام CRectangle بهمراه متغیرها و توابع عضوش تعریف شده است. تعریف تابع عضو کلاس در خطوط 12 الی 16 صورت گرفته و بدنه اصلی برنامه از سطر 18 شروع می شود .

در سطر 20 ما 3 شی از کلاس ایجاد کرده ایم که شی a معمولی و اشیاء b,c از نوع اشاره گر میباشند. در سطر 21 شیئی از نوع اشاره گر بنام d تعریف شده که به دو شی از کلاس CRectangle که بصورت آرایه در نظر گرفته اشاره می نماید. در واقع d شی اشاره گری است که به محل قرارگیری دو شی از کلاس اشاره می کند. و در سطر 22 نیز از کلاس یک شی ایجاد کردیم که به آن با استفاده از کلمه کلیدی new فضایی در حافظه اختصاص داده شده است .

در سطر 23 شی c حاوی آدرس شی a است پس می توان گفت که هر تغییری در a در c هم اعمال خواهد شد. در سطر 24 شی a از تابع عضو کلاس بنام set_values استفاده می کند و پارامترهای 1و2 را به آن می دهد. چون a یک شی معمولی از کلاس است پس برای بکارگیری آن از نقطه استفاده کردیم. اما در سطرهای 25 و26 چون از اشیائی که اشاره گر هستند استفاده کرده ایم پس با استفاده از عملگر مخصوص (->) آنها را به تابع عضو کلاس ربط می دهیم .

اگر دقت کنید می بینید که در سطر 21 ما شی اشاره گر d را بعنوان آرایه ای با طول 2 در نظر گرفته ایم پس دستور سطر 26 فقط به آدرس آن آرایه یعنی اولین خانه اشاره می کند. اما در سطر 27 ما دومین عضو آرایه که خود یک شی از کلاس است را به تابع عضو ربط دادیم به همین علت آنرا دیگر اشاره گر در نظر نمیگیریم و مانند یک شی معمولی از نقطه برای استفاده از کلاس عضو استفاده می کنیم .

در سطرهای 28 الی 32 ما با استفاده از دستور خروجی cout نتایج مورد نظر را در خروجی نمایش می دهیم و در انتها باید اشیائی را که با استفاده از کلمه کلیدی new ایجاد کرده ایم و به آنها در حافظه فضا اختصاص دادیم را با استفاده از کلمه کلیدی delete پاک کرده و فضاهای آنها را به حافظه برگردانیم .

عزیزان باید بادقت کد را مورد مطالعه قرار دهند و مفاهیم فصول قبل مثل اشاره گرها، توابع، آرایه ها و دیگر موارد را درک کرده باشند تا به راحتی قطعه برنامه C++ بالا را تجزیه و تحلیل نمایند .

در ادامه جدولی آماده شده تا عملگرها و حالات اشاره گر به کلاس و شی را بازگو نماید. دقت کنید :

حالت توضیح
*x اشاره شده توسط x
&x آدرس x
x.y عضو y از شی x
x.y عضو y از شی x
x->y عضو y از شی اشاره گر x
(*x)->y عضو y از شی اشاره گر x (همان مفهوم ردیف بالا)
x[0] اولین شی اشاره گر به x
x[1] دومین شی اشاره گر به x
x[n] n+1امین شی اشاره گر به x


آموزش برنامه نویسی C++   آموزش برنامه نویسی C++