امتیاز موضوع:
  • 0 رأی - میانگین امتیازات: 0
  • 1
  • 2
  • 3
  • 4
  • 5
برنامه نویسی شی گرا
نویسنده پیام
Ghoghnus آفلاین
مدیر بخش
*****

ارسال‌ها: 1,497
موضوع‌ها: 270
تاریخ عضویت: آذر ۱۳۸۸

تشکرها : 1652
( 3938 تشکر در 1453 ارسال )
ارسال: #1
Exclamation  برنامه نویسی شی گرا
کلاس ها (Classes) و اشیا (Objects) در برنامه نویسی C++ 
اکنون وقت آن است که برنامه نویسی شی گرا را در عمل یاد گرفته و با اصول تعریف و بکارگیری آن بیشتر آشنا بشویم .
  • کلاس ها (Classes) :
کلاس ها همان نوع داده تجریدی یا انتزاعی (Abstract) هستند. به عبارتی یک نوع داده هستند که توسط برنامه نویس برای کار با داده ها و توابع و رویدادهای مختلفی تعریف می شوند. برای تعریف کلاس از الگوی زیر پیروی می کنیم :
کد:
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 نیز انجام داد .
در ادامه شاهد تعریفی از یک کلاس خواهیم بود :
کد:
#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 بیان شده است که از هر یک از این دو روش برای تعریف دستورات و عملکرد توابع می شود استفاده نمود .
[تصویر:  star_on.gif] نکته) در سطر 12 به نحوه تعریف تابع در خارج از class دقت کنید که ابتدا نوع بازگشتی تابع وسپس نام class و بعد از آن از علامت :: و در نهایت نام تابع و آرگومانهای آن را بیان می کنیم .
در سطر 9 هم چنانچه مشاهده می کنید در همان محل تعریف تابع area() ، دستورات را هم برای تابع نوشته ایم .
برای کلاس CRectangle دو شی یا object ایجاد شده که یکی در سطر 10 و دقیقا بعد از تعریف class، و دیگری در تابع main در سطر 21. دقت کنید که برای ایجاد شی از کلاس در درون بدنه برنامه باید ابتدا نام کلاس و سپس نام شی را بیان نمایید .
هیچ یک از این دو شی ربطی به هم ندارند و هر یک به طور جداگانه از اعضای کلاس استفاده می کنند .
برای دسترسی به اعضای کلاس با استفاده از شی، ابتدا نام کلاس سپس نقطه و در انتها نام عضو که می تواند یک متغیر یا یک تابع یا یک رخداد باشد را ذکر می کنیم، دقت داشته باشید که اگر عضو مورد نظر دارای سطح دسترسی private باشد نمی توان به آن دسترسی داشت زیرا فقط در درون کلاس شناخته شده است و در بیرون از کلاس خود حتی با استفاده از ایجاد شی هم نمیتوان با آنها کار کرد. به کد زیر توجه کنید :
کد:
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
}
فکر کنم که توضیحات در کد گویای همه چیز باشد .
[تصویر:  bulb.jpg] تابع سازنده کلاس (Constructor) :
همانطور که مشاهده کردید در کلاس بالا تابع set_Values() وظیفه مقدار دادن به متغیر ها که همان عرض و طول یک چهار ضلعی هستند را بر عهده داشت. اما در کلاس تابعی بنام سازنده کلاس وجود دارد که کار مقداردهی اولیه به متغیرهای لازم را انجام می دهد .
تابع سازنده، تابع عضو ویژه ای است هم نام با نام کلاس که نوع بازگشتی ندارد و حتی از نوع void هم نیست اما می تواند پارامتر ورودی داشته باشد و دارای دسترسی public می باشد .
هنگامی که از کلاس مربوطه شی ایجاد می شود، تابع سازنده به متغیرهای مربوطه مقدار تعیین شده و فضایی در حافظه را اختصاص می دهد. این کار باعث می شود که از مقداردهی متغیرها و تهی نبودن آنها اطمینان حاصل شود .
[تصویر:  bulb.jpg] تابع مخرب کلاس (Destructor) :
وقتی که کار با شی مورد نظر تمام شد بهتر است که فضایی را که در حافظه به متغیرهای عضو کلاس توسط تابع سازنده یا مولد داده شده است را آزاد کنیم که اینکار را با استفاده از تابع عضو ویژه دیگری بنام تابع مخرب انجام می دهیم. این تابع نیز دارای ویژگیهای تعریفی تابع سازنده است با این تفاوت که با علامت ~ در ابتدای آن تعریف می گردد .
در ادامه به نحوه تعریف و استفاده از توابع عضو سازنده و مخرب در کلاس می پردازیم :
کد:
#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 بکار رفته است دستوری است برای آزادسازی حافظه اشغالی توسط هر شی یا متغیر ، ... در برنامه .
ادامه برنامه کاملا واضح است .
[تصویر:  bulb.jpg] سربارگذاری توابع عضو کلاس در برنامه نویسی C++ (Overloading Constructors) :
مانند سربارگذاری توابع، سازنده های کلاس را نیز میتوان با نامهای مشابه ولی با آرگومانهای متفاوت سربار نمود که در زیر نمونه ای را به همراه هم خواهیم دید :
کد:
#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 توجه نمایید که دیگر از پرانتز باز و بسته استفاده نمی کنیم و در صورت استفاده، کامپایلر از برنامه خطا خواهد گرفت (برخلاف سربارگذاری در توابع) .
[تصویر:  bulb.jpg] تابع سازنده پیش فرض (Default constructor) :
هنگامی که برای یک کلاس تابع سازنده ای تعریف نکنیم، کامپایلر بطور پیش فرض، فرض می کند که کلاس سازنده ای دارد اما بدون پارامتر. به همین دلیل است که وقتی کلاسی بدون تابع سازنده را تعریف می کنیم می توانیم از آن یک شی ایجاد کنیم که کار تعریف تابع سازنده را خود کامپایلر انجام میدهد .
کد:
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 ایجاد نمود و در طول برنامه از آن استفاده کرد و تنها دلیل این موضوع فرض کامپایلر بر وجود یک تابع سازنده بدون پارامتر در کلاس است .
اما اگر خود برای کلاس تابع سازنده ای را تعریف کنیم دیگر کامپایلر فرضی را در نظر نگرفته و بر مبنای تابع سازنده تعریفی ما عمل خواهد کرد مانند کد زیر :
کد:
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 تعریف شده و در حین ایجاد شی از کلاس باید مقداردهی شوند و دیگر کامپایلر مبنا را فرض خود در نظر نمی گیرد و بر اساس کد ما عمل می نماید .
[تصویر:  bulb.jpg] اشاره گر به کلاس (Pointers to Classes) :
اشاره گرها همانطور که می توانند به متغیرها اشاره کنند، می توانند به اشیاء یک کلاس نیز اشاره کنند و چون شی نمونه ای از کلاس است پس به کلاس اشاره می کنند .
در حالت ساده برای دسترسی به اعضای کلاس توسط شی تعریفی، از نقطه (.) استفاده کردیم. اما در اشاره گر به شی باید از ترکیب 2 کاراکتر خط و بزرگتر (<-) استفاده کنیم. با هم مثالی کامل از اشاره گر به شی یا همان کلاس را بررسی می کنیم :
کد:
#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++ بالا را تجزیه و تحلیل نمایند .
 

[تصویر:  a.jpg]

باور کنیم
همانگونه که در غیبت مقصریم در ظهور موثریم!
نیستیم؟

زیر شمشیر غمش رقص کنان باید رفت #  کان که شد کُشته ی او نیک سرانجام افتاد



 چشمک - بهینه شده برای ورژن جدید دانلود پروژه برنامه نويسي
۱۳-آذر-۱۳۹۸, ۱۴:۱۴:۴۰
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : hadikh73, nImaarek, vigraz


موضوعات مرتبط با این موضوع...
موضوع نویسنده پاسخ بازدید آخرین ارسال
  [آموزشی] معرفی یک دوره ی رایگان برنامه نویسی برای مبتدی ها one hacker alone 0 2,519 ۱۲-تير-۱۳۹۴, ۰۰:۰۳:۰۵
آخرین ارسال: one hacker alone
Question درخواست کمک برایه برنامه نویسی ++C yosefpor 10 9,541 ۱۳-خرداد-۱۳۹۳, ۰۰:۲۷:۰۷
آخرین ارسال: babyy
  اشکال در اجرای فایل exeبرنامه نویسی شده با #c taksa2012 2 2,968 ۲۸-مهر-۱۳۹۲, ۱۱:۳۰:۵۳
آخرین ارسال: Ghoghnus
Rolleyes دانلود سوالات برنامه نویسی بیستمین دوره ی مسابقات علمی کاربردی(++VB6,C) javaweb 0 2,628 ۱۸-شهریور-۱۳۹۲, ۰۹:۵۹:۴۰
آخرین ارسال: javaweb
  برنامه نویسی روی پورت موازی asads 1 4,271 ۲۱-مرداد-۱۳۹۲, ۱۵:۵۳:۴۴
آخرین ارسال: maryam727
  دو تا سوال فوری فوتی برنامه نویسی c++ لطفا samadblaj 2 4,438 ۳۱-مرداد-۱۳۹۱, ۲۱:۰۷:۳۶
آخرین ارسال: masterhe3ar
  پورت + برنامه نویسی Mlover 12 13,901 ۱۷-خرداد-۱۳۹۱, ۱۵:۰۷:۱۹
آخرین ارسال: persian_v1989
  [سوال] برنامه نویسی با پورت موازی sadaf-sadaf 3 6,515 ۲۱-دى-۱۳۹۰, ۰۰:۵۷:۲۹
آخرین ارسال: parviz2012
  [سوال] برنامه نویسی سارا انگوری 1 3,497 ۰۹-آبان-۱۳۹۰, ۰۰:۱۹:۴۳
آخرین ارسال: علي برقي
  فارسی نویسی در c++ یا asm tak-fanar 0 3,900 ۰۸-اردیبهشت-۱۳۹۰, ۱۲:۴۴:۵۸
آخرین ارسال: tak-fanar

پرش به انجمن:


کاربرانِ درحال بازدید از این موضوع: 1 مهمان

صفحه‌ی تماس | IranVig | بازگشت به بالا | | بایگانی | پیوند سایتی RSS