ایران سرفراز- نرم افزار وپروژهای دانشجویی


نرم افزار وپروژهای دانشجویی

جلسه اول ودوم کلیات ثابتها- متغیرها در زبان C

<!-- /* Font Definitions */ @font-face {font-family:Mitra; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:auto; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0; mso-gutter-direction:rtl;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:336273680; mso-list-type:hybrid; mso-list-template-ids:1518132838 -1640711818 -1688729308 578484698 -994402906 1692284036 944513110 -314555700 437564794 2062978020;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l1 {mso-list-id:599148374; mso-list-type:hybrid; mso-list-template-ids:115896806 501636638 385240038 202381688 1484441590 -1373895050 1409434208 -1202060372 627366918 1485744244;} @list l1:level1 {mso-level-tab-stop:324.0pt; mso-level-number-position:left; margin-left:324.0pt; text-indent:-18.0pt;} @list l2 {mso-list-id:646012286; mso-list-type:hybrid; mso-list-template-ids:-210187358 -1525525756 633625510 -2054368594 -280859032 -122380792 924477142 -1380932266 -2126511558 -320328594;} @list l2:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l3 {mso-list-id:933630089; mso-list-type:hybrid; mso-list-template-ids:736292756 -1661682796 -789036438 1403428664 -1920990490 -1768366292 772592860 -1388777966 -1408359598 2038326776;} @list l3:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l4 {mso-list-id:1191652396; mso-list-type:hybrid; mso-list-template-ids:2094199790 -1796045148 -1394332032 1924839994 -1047887922 -1431114702 -821023906 207237254 -598935608 2074623520;} @list l4:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l5 {mso-list-id:1236161655; mso-list-type:hybrid; mso-list-template-ids:1718012980 2047637976 -935821046 -1095311822 -475361112 -287267760 1122822196 -1026386814 -704859636 -104710840;} @list l5:level1 {mso-level-start-at:2; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l6 {mso-list-id:1300300868; mso-list-type:hybrid; mso-list-template-ids:-921938128 1523220868 351161170 442665202 460866452 466637342 -1058226020 -1754882720 -235911108 -1488529896;} @list l6:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l7 {mso-list-id:1720321518; mso-list-type:hybrid; mso-list-template-ids:1092283478 1555750218 350096472 -263052810 636010892 -1322344034 -1811149186 931020926 -1679800794 -1274239128;} @list l7:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l8 {mso-list-id:1812361867; mso-list-type:hybrid; mso-list-template-ids:1124749092 -2139619316 998159058 -1867978998 592207156 540175316 105163096 947669570 1071258378 -1872210596;} @list l8:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} @list l9 {mso-list-id:1850871821; mso-list-type:hybrid; mso-list-template-ids:-655833998 -898967920 -169546550 -961108066 -218438646 238989346 -2046664438 758423902 411363040 -684427256;} @list l9:level1 {mso-level-number-format:bullet; mso-level-text:•; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Times New Roman";} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} -->

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

برنامه‌سازی پیشرفته

 

مقدمه و معرفی درس

برنامه‌سازی پیشرفته:

C بیان مفاهیم پیشرفته برنامه‌سازی با استفاده از زبان

 

C کتاب: برنامه‌نویسی به زبان

(ویرایش دوم)

C کلیات در زبان  ثابتها--  

 

 

           

C سابقة تاریخی زبان

B زبان

BCPL زبان

C : زبان

در سال 1972 توسط دنیس ریچی طراحی شد.

 

C ویژگیهای بارز زبان

 

1.      یک زبان میانی است C

 

 

 

سطوح زبانهای برنامه‌سازی

زبانهای سطح پایین

Assembly

زبانهای میانی

Java، ‍‍‍‍C

زبانهای سطح بالا

 

Pascal، Ada، Cobol، Basic

 

ویژگیهای بارز زبان C

 

  1. C یک زبان ساختیافته است.
  2.  
  3. C زبان برنامه‌نویسی سیستم است.
  4.  
  5. C یک زبان قابل حمل است.
  6.  
  7.  
  8. C زبانی قابل انعطاف و قدرتمند است.
  9.  

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

C کلیات زبان

         ; جدا کنندة دستورات از یکدیگر:

هر دستور در یک یا چند سطر

چند دستور در هر سطر

 

 

C کلیات زبان

         /* و /* یا بعد از // توضیحات بین

 

/* this is a sample comment. */

// this is another sample comment.

 

C استانداردسازی زبان

         C گونه‌های مختلف زبان

C : استانداردسازی زبان

          

ANSI C

 

C کامپایلر پیشنهادی زبان

 

Borland C++ 3.1

داده‌های ورودی                  پردازش                 داده‌های خروجی

 
 
 

 


مجموعة دستورات هر زبان برنامه‌نویسی

         دستورات کامپایلر زبان

         دستورات ورودی - خروجی

         دستورات محاسباتی و منطقی

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

جلسة دوم

انواع داده‌های اصلی

int

float

double

char

void

 

boolean  ?!!

 

 

int

 

اعداد صحیح با دامنه محدود

برای کامپیوترهای شخصی دو بایت

32767-

2762+float

اعداد حقیقی  با دامنة محدود

 

 نمایش معمولی

نمایش علمی

12.3E- 4 = 12.00003

 

 

 

double

 

اعداد حقیقی با دقتی بیشتر از float

 

  Char

 کاراکترها نمادها یا حروف

 

a

A

‘+’

‘~’

بسته به محل استفاده عدد یا کاراکتر است.

 

void

 

دادة تهی

دارای کاربردهای مختلف

مثال: توابع فاقد خروجی

 

 

انواع دادهای دیگر

با ترکیب کلمات زیر با برخی از انواع داده‌های اصلی:

signed ، unsigned (با علامت ، بدون علامت)

long ، short

مانند:

unsigned int

long int

unsinged long int

متغیرها

قوانین نامگذاری متغیرها:

         حروف ‘a’ تا ‘z’ ، ‘A’ تا ‘Z’ ، ارقام و ‘_’

         اولین کاراکتر رقم نباشد.

         کلمات کلیدی نمی‌توانند نام متغیر باشند.

 

متغیرها

اسامی مجاز:

count

c124

avg_grade

اسامی غیرمجاز:

1test

bin#tree

for

 

تعریف متغیر

; نام متغیر       نوع داده

int x ;

float m, n ;

char ch1, ch2, ch3 ;

long int count ;

مقدار دهی اولیه به متغیرها

 

int x = 5, y ;

char ch1 = ‘a’, ch2 = ‘A’, ch ;

 

 

ثابتها

تعریف ثابت:

مقدار ثابت       نام ثابت#define  

یا

مقدار = نام ثابت     نوع داده   const 

 

مثال

#define   M    100

#define   P     3.14

 

const   int     n = 100 ;

const   char  c = ‘a’ ;

 

عملگرها

         محاسباتی

         رابطه‌ای

         منطقی

         بیتی

عملگرهای محاسباتی

 

(یکانی)  -

+ , - , * , / , %

++ , --

 

 

مثال

 

- x

x + y

x / y

x % y

 

 

++ و --

 

تفاوت

x ++

و

++ x

 

عبارات محاسباتی

 

ترکیبی از متغیرها، ثابتها و عملگرهای محاسباتی

 

x + y * z / 2 - y

 

دستور انتساب

 

عبارت محاسباتی یا مقدار ثابت = نام متغیر

int x, y = 19, z ;

x = 10 ;

z = x * 2 + y ;

 

تبدیل انواع

char ch ;

int i ; اولویت عملگرها

w = x * y + w

?

w = (x * y) + w

یا

w = x * (y + w)

 

float f, result; ...

result = (ch / i) + f ;

ch = i ;

i = result ;

 

 

 

قواعد اولویت عملگرها و پرانتزها

w = x * y + w

تقدم عملگرهای محاسباتی:

()

++  --

(یکانی)  -

*  /  %

+  -

 

 

عملگرهای رابطه‌ای

>  , >=  , <  , <=

==  , !=

مثال:

x > y

x == y

x != y

عملگرهای منطقی

!

&&

||

مثال:

(x > 10) && (x < y)

! ( x > 20) عملگرهای بیتی

(And)   &

(Or)     |

(Xor)   ^

(Not)   ~

(Right Shift)   >>

(Left Shift)   <<

 

مثال

char x = 7 , y ;

y = x & 2 ;

y = ~y ;

عملگرهای دیگر

         عملگرهای ترکیبی شامل:

+= , - = , *= , /= , %=

که      x = x + y  معادل  x += y

          غیره (در جای خود توضیح داده خواهند شد)

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

   + MOHSEN GHASEMI - ۱٢:۱٤ ‎ق.ظ ; ۱۳۸٩/٥/٢۸

فصل یازدهم در « ترکیب و وراثت » ++C

<!-- /* Font Definitions */ @font-face {font-family:Helvetica; panose-1:2 11 5 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Courier; panose-1:2 7 4 9 2 2 5 2 4 4; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Tms Rmn"; panose-1:2 2 6 3 4 5 5 2 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Helv; panose-1:2 11 6 4 2 2 2 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"New York"; panose-1:2 4 5 3 6 5 6 2 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:System; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"MS Mincho"; panose-1:2 2 6 9 4 2 5 8 3 4; mso-font-alt:"MS 明朝"; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 134676480 16 0 131072 0;} @font-face {font-family:Batang; panose-1:2 3 6 0 0 1 1 1 1 1; mso-font-alt:바탕; mso-font-charset:129; mso-generic-font-family:auto; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 151388160 16 0 524288 0;} @font-face {font-family:SimSun; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:宋体; mso-font-charset:134; mso-generic-font-family:auto; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:1 135135232 16 0 262144 0;} @font-face {font-family:PMingLiU; panose-1:2 1 6 1 0 1 1 1 1 1; mso-font-alt:新細明體; mso-font-charset:136; mso-generic-font-family:auto; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:1 134742016 16 0 1048576 0;} @font-face {font-family:"MS Gothic"; panose-1:2 11 6 9 7 2 5 8 2 4; mso-font-alt:"MS ゴシック"; mso-font-charset:128; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 134676480 16 0 131072 0;} @font-face {font-family:Dotum; panose-1:2 11 6 0 0 1 1 1 1 1; mso-font-alt:돋움; mso-font-charset:129; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 151388160 16 0 524288 0;} @font-face {font-family:SimHei; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:黑体; mso-font-charset:134; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 135135232 16 0 262144 0;} @font-face {font-family:MingLiU; panose-1:2 1 6 9 0 1 1 1 1 1; mso-font-alt:細明體; mso-font-charset:136; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 134742016 16 0 1048576 0;} @font-face {font-family:Mincho; panose-1:2 2 6 9 4 3 5 8 3 5; mso-font-alt:明朝; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 134676480 16 0 131072 0;} @font-face {font-family:Gulim; panose-1:2 11 6 0 0 1 1 1 1 1; mso-font-alt:굴림; mso-font-charset:129; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 151388160 16 0 524288 0;} @font-face {font-family:Century; panose-1:2 4 6 3 5 7 5 2 3 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Angsana New"; panose-1:2 2 6 3 5 4 5 2 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:16777219 0 0 0 65537 0;} @font-face {font-family:"Cordia New"; panose-1:2 11 3 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777219 0 0 0 65537 0;} @font-face {font-family:Mangal; panose-1:0 0 4 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:32768 0 0 0 0 0;} @font-face {font-family:Latha; panose-1:2 0 4 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1048576 0 0 0 0 0;} @font-face {font-family:Sylfaen; panose-1:1 10 5 2 5 3 6 3 3 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:67110535 0 0 0 159 0;} @font-face {font-family:Vrinda; panose-1:1 1 6 0 1 1 1 1 1 1; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:65539 0 0 0 1 0;} @font-face {font-family:Raavi; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:131072 0 0 0 0 0;} @font-face {font-family:Shruti; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:262144 0 0 0 0 0;} @font-face {font-family:Sendnya; panose-1:0 0 4 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Gautami; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:2097152 0 0 0 0 0;} @font-face {font-family:Tunga; panose-1:0 0 4 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:4194304 0 0 0 0 0;} @font-face {font-family:"Estrangelo Edessa"; panose-1:3 8 6 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:-2147459008 0 128 0 0 0;} @font-face {font-family:"Arial Unicode MS"; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Tahoma; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:1627421319 -2147483648 8 0 66047 0;} @font-face {font-family:"Adobe Caslon Pro Bold"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Adobe Caslon Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Adobe Garamond Pro Bold"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Adobe Garamond Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Arno Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Caption"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Display"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro SmText"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Subhead"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Light Display"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Smbd"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Smbd Caption"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Smbd Display"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Smbd SmText"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arno Pro Smbd Subhead"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Bell Gothic Std Black"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Bell Gothic Std Light"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Bickham Script Pro Regular"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:script; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:7 0 0 0 147 0;} @font-face {font-family:"Bickham Script Pro Semibold"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:script; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:7 0 0 0 147 0;} @font-face {font-family:"Birch Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Blackoak Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Brush Script Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Chaparral Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Charlemagne Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Cooper Std Black"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Eccentric Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Garamond Premr Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Garamond Premr Pro Smbd"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Giddyup Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Hobo Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Kozuka Gothic Pro B"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Gothic Pro B"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Gothic Pro EL"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Gothic Pro EL"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Gothic Pro H"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Gothic Pro H"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Gothic Pro L"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Gothic Pro L"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Gothic Pro M"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Gothic Pro M"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Gothic Pro R"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Gothic Pro R"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Mincho Pro B"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Mincho Pro B"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Mincho Pro EL"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Mincho Pro EL"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Mincho Pro H"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Mincho Pro H"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Mincho Pro L"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Mincho Pro L"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Mincho Pro M"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Mincho Pro M"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Kozuka Mincho Pro R"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"\@Kozuka Mincho Pro R"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:515 134676480 16 0 131077 0;} @font-face {font-family:"Letter Gothic Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Lithos Pro Regular"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:decorative; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Mesquite Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Minion Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Minion Pro Cond"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Minion Pro Med"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Minion Pro SmBd"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Myriad Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Myriad Pro Cond"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Myriad Pro Light"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Nueva Std Cond"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"OCR A Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Orator Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Poplar Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Prestige Elite Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Rosewood Std Regular"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Stencil Std"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:modern; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Tekton Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Tekton Pro Cond"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Tekton Pro Ext"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:"Trajan Pro"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:135 0 0 0 155 0;} @font-face {font-family:Marlett; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"Lucida Console"; panose-1:2 11 6 9 4 5 4 2 2 4; mso-font-charset:0; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:-2147482993 6144 0 0 31 0;} @font-face {font-family:"Lucida Sans Unicode"; panose-1:2 11 6 2 3 5 4 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-2147476737 14699 0 0 63 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:536871559 0 0 0 415 0;} @font-face {font-family:"Arial Black"; panose-1:2 11 10 4 2 1 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Comic Sans MS"; panose-1:3 15 7 2 3 3 2 2 2 4; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:Impact; panose-1:2 11 8 6 3 9 2 5 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:Georgia; panose-1:2 4 5 2 5 4 5 2 3 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Franklin Gothic Medium"; panose-1:2 11 6 3 2 1 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Palatino Linotype"; panose-1:2 4 5 2 5 5 5 3 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-536870009 1073741843 0 0 415 0;} @font-face {font-family:"Trebuchet MS"; panose-1:2 11 6 3 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:Webdings; panose-1:5 3 1 2 1 5 9 6 7 3; mso-font-charset:2; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"MV Boli"; panose-1:2 0 5 0 3 2 0 9 0 0; mso-font-charset:1; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 0 256 0 0 0;} @font-face {font-family:"Microsoft Sans Serif"; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:1627421663 -2147483648 8 0 66047 0;} @font-face {font-family:AngsanaUPC; panose-1:2 2 6 3 5 4 5 2 3 4; mso-font-charset:222; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:16777219 0 0 0 65536 0;} @font-face {font-family:BrowalliaUPC; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:222; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777219 0 0 0 65536 0;} @font-face {font-family:"Browallia New"; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777219 0 0 0 65537 0;} @font-face {font-family:CordiaUPC; panose-1:2 11 3 4 2 2 2 2 2 4; mso-font-charset:222; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777219 0 0 0 65536 0;} @font-face {font-family:DilleniaUPC; panose-1:2 2 6 3 5 4 5 2 3 4; mso-font-charset:222; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:EucrosiaUPC; panose-1:2 2 6 3 5 4 5 2 3 4; mso-font-charset:222; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:FreesiaUPC; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:222; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:IrisUPC; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:222; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:JasmineUPC; panose-1:2 2 6 3 5 4 5 2 3 4; mso-font-charset:222; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:KodchiangUPC; panose-1:2 2 6 3 5 4 5 2 3 4; mso-font-charset:222; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:LilyUPC; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:222; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:16777217 0 0 0 65536 0;} @font-face {font-family:Aharoni; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:David; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"David Transparent"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:FrankRuehl; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"Levenim MT"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:Miriam; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"Miriam Transparent"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"Miriam Fixed"; panose-1:0 0 0 9 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"Fixed Miriam Transparent"; panose-1:0 0 0 9 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:Narkisim; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:Rod; panose-1:0 0 0 9 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"Rod Transparent"; panose-1:0 0 0 9 0 0 0 0 0 0; mso-font-charset:177; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:6145 0 0 0 32 0;} @font-face {font-family:"Traditional Arabic"; panose-1:2 1 0 0 0 0 0 0 0 0; mso-font-charset:178; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:24577 0 0 0 64 0;} @font-face {font-family:"Arabic Transparent"; panose-1:2 1 0 0 0 0 0 0 0 0; mso-font-charset:178; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:8193 0 0 0 64 0;} @font-face {font-family:Andalus; panose-1:2 1 0 0 0 0 0 0 0 0; mso-font-charset:178; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:24577 0 0 0 64 0;} @font-face {font-family:"Simplified Arabic"; panose-1:2 1 0 0 0 0 0 0 0 0; mso-font-charset:178; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:8193 0 0 0 64 0;} @font-face {font-family:"Simplified Arabic Fixed"; panose-1:2 1 0 9 0 0 0 0 0 0; mso-font-charset:178; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:8193 0 0 0 64 0;} @font-face {font-family:Kartika; panose-1:2 2 5 3 3 4 4 6 2 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:8388611 0 0 0 1 0;} @font-face {font-family:"Agency FB"; panose-1:2 11 5 3 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Arial Narrow"; panose-1:2 11 5 6 2 2 2 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Arial Rounded MT Bold"; panose-1:2 15 7 4 3 5 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Blackadder ITC"; panose-1:4 2 5 5 5 16 7 2 13 2; mso-font-charset:0; mso-generic-font-family:decorative; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Bodoni MT"; panose-1:2 7 6 3 8 6 6 2 2 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Bodoni MT Black"; panose-1:2 7 10 3 8 6 6 2 2 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Bodoni MT Condensed"; panose-1:2 7 6 6 8 6 6 2 2 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Book Antiqua"; panose-1:2 4 6 2 5 3 5 3 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Bookman Old Style"; panose-1:2 5 6 4 5 5 5 2 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Bradley Hand ITC"; panose-1:3 7 4 2 5 3 2 3 2 3; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Calisto MT"; panose-1:2 4 6 3 5 5 5 3 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Castellar; panose-1:2 10 4 2 6 4 6 1 3 1; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Century Gothic"; panose-1:2 11 5 2 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Century Schoolbook"; panose-1:2 4 6 4 5 5 5 2 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Copperplate Gothic Bold"; panose-1:2 14 7 5 2 2 6 2 4 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Copperplate Gothic Light"; panose-1:2 14 5 7 2 2 6 2 4 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Curlz MT"; panose-1:4 4 4 4 5 7 2 2 2 2; mso-font-charset:0; mso-generic-font-family:decorative; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Edwardian Script ITC"; panose-1:3 3 3 2 4 7 7 13 8 4; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Elephant; panose-1:2 2 9 4 9 5 5 2 3 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Engravers MT"; panose-1:2 9 7 7 8 5 5 2 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Eras Bold ITC"; panose-1:2 11 9 7 3 5 4 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Eras Demi ITC"; panose-1:2 11 8 5 3 5 4 2 8 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Eras Light ITC"; panose-1:2 11 4 2 3 5 4 2 8 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Eras Medium ITC"; panose-1:2 11 6 2 3 5 4 2 8 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Felix Titling"; panose-1:4 6 5 5 6 2 2 2 10 4; mso-font-charset:0; mso-generic-font-family:decorative; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Forte; panose-1:3 6 9 2 4 5 2 7 2 3; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Franklin Gothic Book"; panose-1:2 11 5 3 2 1 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Franklin Gothic Demi"; panose-1:2 11 7 3 2 1 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Franklin Gothic Demi Cond"; panose-1:2 11 7 6 3 4 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Franklin Gothic Heavy"; panose-1:2 11 9 3 2 1 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Franklin Gothic Medium Cond"; panose-1:2 11 6 6 3 4 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"French Script MT"; panose-1:3 2 4 2 4 6 7 4 6 5; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Garamond; panose-1:2 2 4 4 3 3 1 1 8 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:Gigi; panose-1:4 4 5 4 6 16 7 2 13 2; mso-font-charset:0; mso-generic-font-family:decorative; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Gill Sans MT Ext Condensed Bold"; panose-1:2 11 9 2 2 1 4 2 2 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Gill Sans MT"; panose-1:2 11 5 2 2 1 4 2 2 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Gill Sans MT Condensed"; panose-1:2 11 5 6 2 1 4 2 2 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Gill Sans Ultra Bold"; panose-1:2 11 10 2 2 1 4 2 2 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Gill Sans Ultra Bold Condensed"; panose-1:2 11 10 6 2 1 4 2 2 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Gloucester MT Extra Condensed"; panose-1:2 3 8 8 2 6 1 1 1 1; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Goudy Old Style"; panose-1:2 2 5 2 5 3 5 2 3 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Goudy Stout"; panose-1:2 2 9 4 7 3 11 2 4 1; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Haettenschweiler; panose-1:2 11 7 6 4 9 2 6 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"Imprint MT Shadow"; panose-1:4 2 6 5 6 3 3 3 2 2; mso-font-charset:0; mso-generic-font-family:decorative; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Lucida Sans"; panose-1:2 11 6 2 3 5 4 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Lucida Sans Typewriter"; panose-1:2 11 5 9 3 5 4 3 2 4; mso-font-charset:0; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"MS Outlook"; panose-1:5 1 1 0 1 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"Maiandra GD"; panose-1:2 14 5 2 3 3 8 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Monotype Corsiva"; panose-1:3 1 1 1 1 2 1 1 1 1; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"OCR A Extended"; panose-1:2 1 5 9 2 1 2 1 3 3; mso-font-charset:0; mso-generic-font-family:modern; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Palace Script MT"; panose-1:3 3 3 2 2 6 7 12 11 5; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Papyrus; panose-1:3 7 5 2 6 5 2 3 2 5; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Perpetua; panose-1:2 2 5 2 6 4 1 2 3 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Perpetua Titling MT"; panose-1:2 2 5 2 6 5 5 2 8 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Pristina; panose-1:3 6 4 2 4 4 6 8 2 4; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Rage Italic"; panose-1:3 7 5 2 4 5 7 7 3 4; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Rockwell; panose-1:2 6 6 3 2 2 5 2 4 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Rockwell Condensed"; panose-1:2 6 6 3 5 4 5 2 1 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Rockwell Extra Bold"; panose-1:2 6 9 3 4 5 5 2 4 3; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Script MT Bold"; panose-1:3 4 6 2 4 6 7 8 9 4; mso-font-charset:0; mso-generic-font-family:script; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:"Tw Cen MT"; panose-1:2 11 6 2 2 1 4 2 6 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Tw Cen MT Condensed"; panose-1:2 11 6 6 2 1 4 2 2 3; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"Wingdings 2"; panose-1:5 2 1 2 1 5 7 7 7 7; mso-font-charset:2; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"Wingdings 3"; panose-1:5 4 1 2 1 8 7 7 7 7; mso-font-charset:2; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"Bookshelf Symbol 7"; panose-1:5 1 1 1 1 1 1 1 1 1; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"MS Reference Sans Serif"; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:536871559 0 0 0 415 0;} @font-face {font-family:"MS Reference Specialty"; panose-1:5 0 5 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"Tw Cen MT Condensed Extra Bold"; panose-1:2 11 8 3 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:7 0 0 0 3 0;} @font-face {font-family:"MT Extra"; panose-1:5 5 1 2 1 2 5 2 2 2; mso-font-charset:2; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} ins {mso-style-type:export-only; text-decoration:none;} span.msoIns {mso-style-type:export-only; mso-style-name:""; text-decoration:underline; text-underline:single;} span.msoDel {mso-style-type:export-only; mso-style-name:""; text-decoration:line-through; color:red;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصل یازدهم

C++ در « ترکیب و وراثت »

12 مقدمه ‐1

اغلب اوقات برای ایجاد یک کلاس جدید، نیازی نیست که همه چیز از اول

طراحی شود. می توانیم برای ایجاد کلاس مورد نظر، از تعاریف کلاس هایی که قبلا

ساخته ایم، استفاده نماییم. این باعث صرف هجویی در وقت و استحکام منطق برنامه

می شود. در شی گرایی به دو شیوه می توان این کار را انجام داد: ترکیب 1 و وراثت 2. در

این فصل خواهیم دید که چگونه و چه مواقعی می توانیم از این دو شیوه بهره ببریم.

12 ترکیب ‐2

ترکیب کلاس ها (یا تجمیع کلاس ها) یعنی استفاده از یک یا چند کلاس دیگر در

داخل تعریف یک کلاس جدید. هنگامی که عضو داده ای کلاس جدید، شیئی از کلاس

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

کلاس زیر نگاه کنید.

1 – Composition 2 – Inheritance

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

358 برنامه سازی پیشرفته

Date 11 کلاس ‐ * مثال 1

را نشان می دهد که اشیای این کلاس برای نگهداری Date کد زیر، کلاس

تاریخ استفاده می شوند.

class Date

{ public:

Date(int y=0, int m=0, int d=0) :

year(y), month(m), day(d) {};

void setDate(int y, int m, int d)

{ year = y; month = m; day = d; }

void getDate()

{ cin >> year >> month >> day ; }

void showDate()

{ cout << year << '/' << month << '/' << day ; }

private:

int year, month, day;

}

int main()

{ Date memory(1359,6,31);

cout << "SADDAM attacked to IRAN at ";

memory.showDate();

memory.setDate(1367,4,27);

cout << "\nThat war finished at ";

memory.showDate();

cout << "\nEnter your birthday: ";

memory.getDate();

cout << "\nYour birthday is ";

memory.showDate();

}

SADDAM attacked to IRAN at 1359/6/31

That war finished at 1367/4/27

Enter your birthday: 1358 6 15

Your birthday is 1358/6/15

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل یازدهم / ترکیب و وراثت 359

 

Book 11 کلاس ‐ * مثال 2

را نشان می دهد که اشیای این کلاس برخی از مشخصات Book کد زیر، کلاس

یک کتاب را نگهداری می کنند:

class Book

{ public:

Book(char* n = " ", int i = 0, int p = 0) :

name(n), id(i), page(p) { }

void printName() { cout << name; }

void printId() { cout << id; }

void printPage() { cout << page; }

private:

string name, author;

int id, page;

}

int main()

{ Book reference("C++", 1, 450);

cout << " reference id pages " << endl;

cout << "-----------------------------" << endl;

cout << " " ; reference.printName();

cout << " " ; reference.printId();

cout << " " ; reference.printPage();

}

reference id pages

-----------------------------

C++ 1 450

را بهبود دهیم Book اکنون می خواهیم با ترکیب این دو کلاس، امکانات کلاس

تا مشخصات یک کتاب و تاریخ انتشار آن را نگهداری کند.

Book 11 بهبود دادن کلاس ‐ * مثال 3

#include "Date.h"

class Book

{ public:

Book(char* n = " ", int i = 0, int p = 0) :

 

 

360 برنامه سازی پیشرفته

name(n), id(i), page(p) { }

void printName() { cout << name; }

void printId() { cout << id; }

void printPage() { cout << page; }

void setDOP(int y, int m, int d)

{ publish.setDate(y, m, d) ; }

void showDOP() { publish.showDate(); }

private:

string name, author;

int id, page;

Date publish;

}

با دقت در این کلاس بهبود یافته، می بینیم که یک عضو داد های خصوصی از نوع کلاس

درون اعضای آن وجود دارد. همچنین دو تابع عضو عمومی جدید Date

نیز به این کلاس افزوده شده. به بدنۀ این دو تابع نگاه showDOP() و setDOP()

در بدنۀ این دو تابع showDate() و setDate() کنید. دو تابع دیگر به نا مهای

هستند. Date قرار دارند. این دو تابع، عضو کلاس

است، می توانیم Date از نوع publish چون

را برای آن صدا بزنیم. Date توابع عضو کلاس

را در فایل Date توجه کنید که تعاریف کلاس

گذاشته ایم و برای "Date.h" جداگانه ای به نام

فایل ،Book ترکیب کردن این کلاس با کلاس

را Book کرده ایم. کلاس include مذکور را

Date می توانیم به شکل مقابل مجسم کنیم. کلاس

به عنوان یک عضو داده ای در بخش اعضای داده ای

قرار گرفته است. Book کلاس

حالا می توانیم این کلاس مرکب را در برنامه استفاده کنیم:

int main()

{ Book reference("C++", 1, 450);

reference.setDOP(1384, 6, 15);

Book()

printName()

printId()

printPage()

setDOP()

showDOP()

name, author

id, page;

Date()

setDate()

getDate()

showDate()

year, month, day

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل یازدهم / ترکیب و وراثت 361

cout << " reference id pages DOP " << endl;

cout << "---------------------------------------" << endl;

cout << " " ; reference.printName();

cout << " "; reference.printId();

cout << " " ; reference.printPage();

cout << " " ; reference.showDOP();

}

reference id pages DOP

---------------------------------------

C++ 1 450 1384/6/15

11 وراثت ‐3

وراثت روش دیگری برای ایجاد کلاس جدید از روی کلاس قبلی است. گاهی

نیز می گویند. اگر از قبل با برنام هنویسی مبتنی بر پنجر هها آشنایی « اشتقاق » به وراثت

را فراوان دیده اید. این موضوع « کلاس مشتق شده » مختصر داشته باشید، احتمالا عبارت

به خوبی اهمیت وراثت را آشکار می نماید.

در دنیای واقعی، وراثت به این معناست که هر فرزندی خواص عمومی را از والد

خود به ارث می گیرد، مثل رنگ چشم یا رنگ مو یا چهرۀ ظاهری یا رفتارهای غریزی

و ... . در دنیای نرم افزار نیز وراثت به همین معناست. یعنی کلاس جدید را طوری

قبلا تعریف x تعریف کنیم که اعضای کلاس دیگر را به کار بگیرد. فرض کنید کلاس

به شکل زیر است: x از کلاس y شده و وجود دارد. نحو کلی برای اشتقاق کلاس

class Y : public X

{

// ...

};

public مشتق شده است. عبارت x از کلاس y در این حالت می گوییم که کلاس

فقط به اعضای عمومی y بعد از علامت کولن برای تاکید بر این معناست که کلاس

« کلاس پایه » یا « کلاس والد 2 » کلاس اصلی 1 یا x دسترسی دارد. به کلاس x کلاس

می گوییم. « کلاس مشتق شده » یا « کلاس فرزند 4 » زیرکلاس 3 یا y می گوییم و به کلاس

1 – Base class 2 – Parent class

3 – Sub class 4 – Child class

 

 

362 برنامه سازی پیشرفته

کلاس فرزند می تواند علاوه بر اعضای به ارث برده شده، اعضای عمومی و خصوصی

خاص خود را نیز داشته باشد. به کد زیر دقت کنید:

class X

{ public:

int a;

private:

int b;

};

class Y : public X

{ public:

int c;

private:

int d;

}

به Y دارد. کلاس b و یک عضو خصوصی به نام a یک عضو عمومی به نام X کلاس

را به ارث می برد. یعنی x اعلان شده. پس عضو عمومی کلاس X عنوان فرزند کلاس

هم c هست. همچنین یک عضو عمومی مخصوص به خود به نام a دارای Y کلاس

است، نمی تواند توسط کلاس X یک عضو خصوصی از کلاس والد یعنی b دارد. چون

مستقیما دستیابی شود. Y فرزند یعنی

فقط یک عضو خصوصی Y بنابراین کلاس

را می توان Y و X دارد. کلاس های d به نام

به شکل مقابل تصور نمود. تصویر نشان

را هم دارد ولی b عضو Y می دهد که کلاس

اجازۀ دسترسی مستقیم به آن را ندارد. به مثال زیر توجه کنید.

Book از کلاس Ebook 11 مشتق کردن کلاس ‐ * مثال 4

می خواهیم کلاسی برای نگهداری مشخصات کتا بهای الکترونیکی بسازیم.

کتاب های الکترونیکی زیرمجموعه ای از کتاب های کلی هستند. پس منطقی است به

که قبلا ایجاد Book را از ابتدا ایجاد کنیم، آن را از کلاس Ebook جای این که کلاس

Book کردیم، مشتق کنیم. در این صورت اغلب توابع و متغیرهای مورد نیاز از کلاس

int a

int b

int a

int c

int d

int b

X Y

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

فصل یازدهم / ترکیب و وراثت 363

به ارث گرفته می شوند و نیازی به ایجاد آ نها نیست. فقط کافی است توابع و داده های

را به کلاس مشتق شده اضافه کنیم: Ebook خاص کلاس

#include "Book.h"

class Ebook : public Book

{ public:

Ebook(char* n, int i=0, int p=0) :

Book(n,i,p), format("PDF"), size(0) {}

void printFormat() { cout << format; }

void setSize(int s){ size = s; }

void setFormat(char* f) { format = f; }

void printSize() { cout << size; }

private:

string format;

int size;

}

int main()

{ Ebook reference("C++", 1, 450);

reference.setSize(5500);

cout << " Ebook id pages format size(KB) \n";

cout << "----------------------------------------- \n";

cout << " " ; reference.printName();

cout << " "; reference.printId();

cout << " "; reference.printPage();

cout << " "; reference.printFormat();

cout << " "; reference.printSize();

}

Ebook id pages format size(KB)

-----------------------------------------

C++ 1 450 PDF 5500

در کلاس printPage() و printId() و printName() گرچه توابع

مشتق شده، Book اعلان و تعریف نشده اند، اما چون این کلاس از کلاس Ebook

همۀ اعضای عمومی آن را به ارث می گیرد و دیگر نیازی به اعلان آن ها نیست. این مثال

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

364 برنامه سازی پیشرفته

نشان می دهد که با استفاده از اعضای عمومی به ارث گرفته شده از کلاس والد، می توان

به اعضای خصوصی آن دسترسی داشت. دقت کنید که چگونه در تابع سازندۀ کلاس

استفاده کرده و به اعضای خصوصی کلاس Book از تابع سازندۀ کلاس Ebook

دستیابی نموده ایم. Book

11 اعضای حفاظت شده ‐4

در مثال قبل نمی تواند مستقیما به اعضای خصوصی Ebook گرچه کلاس

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

والد به ارث برده، می تواند به اعضای خصوصی آن کلاس دستیابی کند. این محدودیت

بزرگی محسوب م یشود. اگر توابع عضو عمومی کلاس والد انتظارات کلاس فرزند را

برآورده نسازند، کلاس فرزند ناکارآمد می شود. اوضاع زمانی وخیم تر می شود که هیچ

تابع عمومی برای دسترسی به یک دادۀ خصوصی در کلاس والد وجود نداشته باشد.

داریم که author 11 یک دادۀ خصوصی به نام ‐ مثال 2 Book در کلاس

به هیچ ترتیبی نمی توانیم به این Ebook بیان گر نام نویسنده است. در کلاس فرزند

Ebook عضو دسترسی پیدا کنیم. می توانیم این دادۀ عضو را به شکل صریح در کلاس

است و Book زیرمجموعه ای از Ebook بگنجانیم ولی این کار منطقی نیست زیرا

توصیه می کند به جای C++ باید بتواند خواص آن را به کار بگیرد. در چنین مواقعی

اعلان کنیم، آن (private) را در کلاس والد به صورت خصوصی author این که

یا protected اعلان نماییم. اعضای (protected) را به شکل حفاظت شده

حفاظت شده 1 اعضایی هستند که مثل اعضای خصوصی از خارج کلاس قابل دستیابی

نیستند ولی مثل اعضای عمومی می توانند توسط کلا سهای فرزند مستقیما دستیابی

شوند. به مثال زیر توجه کنید.

protected با اعضای داده ای Book 11 کلاس ‐ * مثال 5

11 هستند با این تفاوت که اعضای ‐ کدهای زیر همان کدهای مثال 2

تبدیل شد هاند و توابع دستیابی protected به اعضای Book کلاس private

1 – Protected members

فصل یازدهم / ترکیب و وراثت 365

افزوده شده: Ebook به کلاس مشتق شدۀ printAuthor() و setAuthor()

class Book

{ public:

Book(char* n = " ", int i = 0, int p = 0) :

name(n), id(i), page(p) { }

void printName() { cout << name; }

void printId() { cout << id; }

void printPage() { cout << page; }

protected:

string name, author;

int id, page;

}

class Ebook : public Book

{ public:

Ebook(char* n, int i=0, int p=0) :

Book(n,i,p), format("PDF"), size(0) {}

void setAuthor(char* a) { author = a; }

void setSize(int s){ size = s; }

void setFormat(char* f) { format = f; }

void printAuthor() { cout << author; }

void printFormat() { cout << format; }

void printSize() { cout << size; }

protected:

string format;

int size;

}

قابل دستیابی Ebook از درون زیرکلاس Book حالا همۀ اعضای حفاظت شدۀ کلاس

هستند:

int main()

{ Ebook reference("C++", 1, 450);

reference.setSize(5500);

reference.setAuthor("P.N.U");

cout << "\n Ebook name: "; reference.printName();

cout << "\n id: "; reference.printId();

366 برنامه سازی پیشرفته

cout << "\n pages: "; reference.printPage();

cout << "\n format: "; reference.printFormat();

cout << "\n size(KB): "; reference.printSize();

cout << "\n Author: "; reference.printAuthor();

}

Ebook name: C++

id: 1

pages: 450

format: PDF

size(KB): 5500

Author: P.N.U

بنابر آ نچه گفتیم، اعضای یک کلاس سه گروه هستند: اعضای عمومی یا

که از بیرون کلاس و از درون کلاس های فرزند مستقیما قابل دستیابی اند؛ public

که فقط از درون همان کلاس یا توابع دوست کلاس private اعضای خصوصی یا

که از بیرون protected می توان به آ نها دسترسی داشت؛ اعضای حفاظت شده یا

کلاس قابل دستیابی نیستند ولی از درون همان کلاس یا درون کلاس های فرزند یا

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

یک کلاس به شکل زیر است:

class X

{ public:

// public members

protected:

// protected members

private:

// private members

};

در نظر داشته باشید که اعضای حفاظت شده از کلاس والد، در کلاس فرزند نیز به

منظور می شوند. protected عنوان اعضای

دارند، چه نیازی به protected ممکن است بپرسید با خواصی که اعضای

است؟ برای پاسخ به این سوال یادآوری می کنیم که از مزیت های private اعضای

مهم شی گرایی، مخفی سازی اطلاعات است. همیشه این طور نیست که بخواهیم همۀ

 

 

فصل یازدهم / ترکیب و وراثت 367

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

بگذاریم که نوع کاغذ مصرفی در کتاب paperkind یک عضو داده ای با نام Book

اصلا بی معناست. Ebook را نشان می دهد. طبیعی است که چنین عضوی در کلاس

را به paperkind عضو داده ای Ebook بنابراین لازم نیست (و نباید) که کلاس

ارث بگیرد و این عضو باید از دسترس دور بماند. عقیدۀ کلی بر این است که هر عضو

اعلان کنید مگر این که احتمال بدهید آن عضو private داده ای کلاس را به شکل

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

اعلان نمایید. protected شکل

11 غلبه کردن بر وراثت ‐5

همۀ اعضای عمومی و حفاظت شدۀ Y باشد، آنگاه اشیای X زیر کلاسی از Y اگر

printName() تابع دستیابی Ebook را ارث می برند. مثلا تمامی اشیای X کلاس

« عضو موروثی » یک printName() را به ارث می برند. به تابع Book از کلاس

می گوییم. گاهی لازم است یک نسخۀ محلی از عضو موروثی داشته باشیم. یعنی کلاس

فرزند، عضوی هم نام با عضو موروثی داشته باشد که مخصوص به خودش باشد و

داشته باشد و p یک عضو عمومی به نام X ارثی نباشد. برای مثال فرض کنید کلاس

را خواهند p عضو موروثی Y باشد. در این حالت اشیای کلاس X زیر کلاس Y کلاس

به شکل صریح اعلان کنیم، Y در زیرکلاس p داشت. حال اگر یک عضو به همان نام

عضو » ، این عضو جدید، عضو موروثی هم نامش را مغلوب می کند. به این عضو جدید

غالب p به عضو y1.p ، باشد Y یک شی از کلاس y می گوییم. بنابراین اگر 1 « غالب

موروثی دسترسی داشت. p موروثی. البته هنوز هم می توان به p اشاره دارد نه به

موروثی دستیابی دارد. p به y1.X::p عبارت

هم می توان اعضای داده ای موروثی را مغلوب کرد و هم اعضای تابعی موروثی

باشد و در زیرکلاس f() دارای یک عضو تابعی عمومی به نام X را. یعنی اگر کلاس

به تابع غالب اشاره y1.f() را به شکل صریح اعلان کنیم، آنگاه f() نیز تابع Y

به تابع موروثی اشاره دارد. در برخی از مراجع به توابع غالب y1.X::f() دارد و

 

 

368 برنامه سازی پیشرفته

می نامند. ما در این کتاب هر dominate می گویند و داده های غالب را override

دو مفهوم را به عنوان اعضای غالب به کار می بریم. به مثال زیر نگاه کنید.

11 اعضای داده ای و تابعی غالب ‐ * مثال 6

class X

{ public:

void f() { cout << "Now X::f() is running\n"; }

int a;

};

class Y : public X

{ public:

void f() { cout << "Now Y::f() is running\n"; }

// this f() overrides X::f()

int a;

// this a dominates X::a

};

را دارند. به همین دلیل تابع X همان مشخصات اعضای کلاس Y اعضای زیرکلاس

را مغلوب می کند (X::f()) موروثی f() اعلان شده، تابع Y که در زیرکلاس f()

را مغلوب (X::a) موروثی a اعلان شده نیز عضو Y که در زیرکلاس a و عضو

می نماید. برنامۀ آزمون زیر این مطلب را تایید می کند:

int main()

{ X x1;

x1.a = 22;

x1.f();

cout << "x1.a = " << x1.a << endl;

Y y1;

y1.a = 44; // assigns 44 to the a defined in Y

y1.X::a = 66; // assigns 66 to the a defined in X

y1.f(); // calls the f() defined in Y

y1.X::f(); // calls the f() defined in X

cout << "y1.a = " << y1.a << endl;

cout << " y1.X::a = " << y1.X::a << endl;

 

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

 

فصل یازدهم / ترکیب و وراثت 369

X x2 = Y1;

cout << "x2.a = " << x2.a << endl;

}

X::f() is running

x1.a = 22

Y::f() is running

X::f() is running

y1.a = 44

y1.X::a = 66

x2.a = 66

دارد. به f() و دو عضو تابعی مجزای a دو عضو داده ای مجزای y می بینید که شیء 1

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

جداسازی حوزه :: می توان به اعضای موروثی نیز دسترسی داشت.

شیئی از کلاس x نکتۀ مهمی وجود دارد. 2 x2 = y در دستور جایگزینی ; 1

شیئی از کلاس فرزند. وقتی قرار باشد یک شی از کلاس فرزند درون y والد است و 1

یک شی از کلاس والد کپی شود، به طور پیش فرض اعضای موروثی کلاس فرزند برای

در y1.X::a جایگزینی انتخاب می شوند نه اعضای غالب. یعنی در چنین حالتی

سعی کنید علت را توضیح دهید) ) . y1.a کپی می شود نه x2.a

در برنام ههای واقعی، از توابع غالب بسیار استفاده می شود اما استفاده از داد ههای

غالب چندان مرسوم نیست. اغلب این طور است که نوع یک عضو داد های در کلاس

a فرزند با نوع همان عضو در کلاس والد متفاوت است. برای مثال اگر عضو داده ای

در کلاس فرزند از نوع a باشد، آنگاه عضو داده ای صریح int در کلاس والد از نوع

اعلان می شود. double

سازنده های پیش فرض و نابودگرها در وراثت رفتار متفاوتی دارند. به این

صورت که سازندۀ کلاس فرزند قبل از اجرای خودش، سازندۀ کلاس والدش را فرا

می خواند. نابودگر کلاس فرزند نیز پس از اجرای خودش، نابودگر کلاس والدش را

فراخوانی می کند. به مثال زیر توجه نمایید.

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

 

370 برنامه سازی پیشرفته

11 سازنده ها و نابودکننده های والد ‐ * مثال 7

class X

{ public:

X() { cout << "X::X() constructor executing\n"; }

~X() { cout << "X::X() destructor executing\n"; }

};

clas Y : public X

{ public:

Y() { cout << "Y::Y() constructor executing\n"; }

~Y() { cout << "Y::Y() destructor executing\n"; }

};

clas Z : public Y

{ public:

Z(int n) {cout << "Z::Z(int) constructor executing\n";}

~Z() { cout << "Z::Z() destructor executing\n"; }

};

int main()

{ Z z(44);

}

X::X() constructor executing

Y::Y() constructor executing

Z::Z(int) constructor executing

Z::Z() destructor executing

Y::Y() destructor executing

X::X() destructor executing

می باشد. در X فرزند کلاس Y است که خود Y فرزند کلاس Z در برنامۀ بالا کلاس

نمونه سازی شده. پس انتظار این است Z یک شی از نوع کلاس main() بدنۀ تابع

فراخوانی شود. اما تصویر خروجی نیز نشان می دهد که قبل از Z که سازندۀ کلاس

فراخوانی Y تابع سازندۀ کلاس والدش یعنی سازندۀ کلاس ،Z فراخوانی سازندۀ

سازندۀ کلاس ،Y است، پس قبل از فراخوانی سازندۀ کلاس X فرزند Y می شود. چون

و X ابتدا سازندۀ کلاس Z فراخوانی می شود. لذا هنگام ایجاد یک شی از کلاس X

فراخوانی می شود. Z و در نهایت سازندۀ کلاس Y سپس سازندۀ کلاس

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل یازدهم / ترکیب و وراثت 371

به پایان عمرش می رسد. پس باید Z برسیم، شیء main() وقتی به پایان تابع

فراخوانی شود. همین اتفاق هم می افتد اما پس از فراخوانی نابودگر Z نابودگر کلاس

هم فراخوانی می شود. پس از فراخوانی Y نابودگر کلاس والدش یعنی ،Z کلاس

است فراخوانی می شود. دقت کنید Y نیز که والد X نابودگر کلاس ،Y نابودگر کلاس

که سازنده های والد از برترین کلاس به زیرترین کلاس اجرا می شوند ولی نابودگرها از

زیرترین کلاس به سمت برترین کلاس اجرا می شوند. اما چرا چنین اتفاقی می افتد؟

را به ارث می گیرد. سازندۀ X باشد، اعضای کلاس X فرزند کلاس Y اگر کلاس

راجع به اعضای صریح این کلاس آگاهی دارد ولی از اعضای کلاس والد Y کلاس

چه میزان Y چیزی نمی داند. بنابراین هنگام اجرا می داند برای اعضای صریح کلاس

حافظه منظور کند اما نمی داند برای اعضای موروثی چقدر حافظه نیاز است. از کجا

می توان میزان حافظۀ مورد نیاز اعضای موروثی را فهمید؟ از سازندۀ والد. به همین

دلیل است که هر سازنده قبل از اجرای خودش، سازندۀ والدش را فرا می خواند.

سازندۀ والد حافظۀ مورد نیاز برای اعضای والد را تخصیص داده و این حافظه را به

سازندۀ فرزند تحویل می دهد. سازندۀ فرزند نیز حافظۀ لازم برای اعضای صریح را

تخصیص داده و به میزان قبلی می افزاید و به این ترتیب شیء فرزند با حافظۀ کافی

متولد می شود. هنگام نابود کردن شیء فرزند نیز ابتدا نابودگر کلاس فرزند حافظۀ

تخصیصی به اعضای صریح را آزاد می کند اما حافظۀ تخصیص یافته به اعضای موروثی

بلاتکلیف باقی می مانند. به همین دلیل لازم است نابودکنندۀ کلاس والد نیز فراخوانی

شود تا این حافظۀ اضافی آزاد شود.

11 اشاره گرها در وراثت ‐6

اشاره گری از p در شی گرایی خاصیت جالبی وجود دارد و آن این است که اگر

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

کد زیر نگاه کنید:

class X

{ public:

void f();

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

372 برنامه سازی پیشرفته

}

class Y : public X // Y is a subclass of X

{ public:

void f();

}

int main()

{ X* p; // p is a pointer to objects of base class X

Y y;

p = &y; // p can also point to objects of subclass Y

}

است نیز X که فرزند Y است، اما آن را می توان به اشیای کلاس X* از نوع p گرچه

است. حالا در کد فوق *p.f() معادل p->f() اشاره داد. یادآوری می کنیم که

فراخوانی p->f() اشاره کند و Y است به یک شیء X* که از نوع p تصور کنید

انتظار داریم که ؟ Y::f() یا X::f() ؟ فراخوانی می شود f() شود. اکنون کدام

تعریف شده است و فقط X* از نوع p . فراخوانی شود ولی چنین نیست Y::f()

به چه شیئی اشاره دارد. مهم این است p را می شناسد. اصلا مهم نیست که X::f()

است و توابع آن را می شناسد. مثال زیر این مطلب را تایید می کند. X* که از کلاس

11 اشاره گری از کلاس والد به شیئی از کلاس فرزند ‐ * مثال 8

است. هر دوی این کلاس ها دارای یک X زیرکلاسی از Y در برنامۀ زیر، کلاس

تعریف شده: X* اشاره گری از نوع p هستند و f() عضو تابعی به نام

class X

{ public:

void f() { cout << "X::f() executing\n"; }

};

class Y : public X

{ public:

void f() { cout << "Y::f() executing\n"; }

}

int main()

{ X x; فصل یازدهم / ترکیب و وراثت 373

X* p = &x;

p->f(); // invokes X::f() because p has type X*

p = &y;

p->f(); // invokes X::f() because p has type X*

}

X::f() executing

X::f() executing

و یک X از کلاس x فراخوانی شده. یک بار برای شیء p->f() در برنامۀ بالا دو بار

به اشیای p ولی در هر دو بار بدون توجه به این که Y از کلاس y بار هم برای شیء

فراخوانی شده. X::f() چه کلاسی اشاره دارد، فقط

مشخص است که اثر فوق مطلوب به نظر نمی رسد. انتظار داریم که برای اشیای

هم هنگام X فراخوانی شود و برای اشیای Y::f() تابع p->f() هنگام اجرای ،Y

توابع » فرا خوانده شود. برای برآوردن این انتظار، از X::f() تابع p->f() اجرای

استفاده می کنیم. « مجازی

11 توابع مجازی و چندریختی ‐7

مشخص می شود. وقتی virtual تابع مجازی 1 تابعی است که با کلمۀ کلیدی

یک تابع به شکل مجازی اعلان می شود، یعنی در حداقل یکی از کلاس های فرزند نیز

تابعی با همین نام وجود دارد. توابع مجازی امکان می دهند که هنگام استفاده از

اشاره گرها، بتوانیم بدون در نظر گرفتن نوع اشاره گر، به توابع شیء جاری دستیابی

کنیم. به مثال زیر دقت کنید.

11 استفاده از توابع مجازی ‐ * مثال 9

از کلاس f() 11 است با این تفاوت که تابع ‐ این برنامه، همان برنامۀ مثال 8

والد به شکل یک تابع مجازی اعلان شده است:

class X

{ public:

virtual void f() { cout << "X::f() executing\n"; }

1 – Virtual function

 

Y y;

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

374 برنامه سازی پیشرفته

};

class Y : public X

{ public:

void f() { cout << "Y::f() executing\n"; }

}

int main()

{ X x;

Y y;

X* p = &x;

p->f(); // invokes X::f()

p = &y;

p->f(); // invokes Y::f()

}

X::f() executing

Y::f() executing

X::f() ، فراخوانی شود p->f() اشاره کند و تابع X به شیئی از نوع p اکنون وقتی

فراخوانی شود، p->f() اشاره کند و تابع Y به شیئی از نوع p اجرا می شود و وقتی

یا چندریختی می گویند « چندشکلی » ، اجرا می شود. به این مفهوم Y::f() این دفعه

به چه نوع شیئی اشاره کند، نتایج متفاوتی p بسته به این که p->f() زیرا فراخوانی

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

می کنند. مثال زیر، نمونۀ مفیدتری از چندریختی را نشان می دهد.

11 چندریختی از طریق توابع مجازی ‐ * مثال 10

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

مورد انتظار است کار نمی کند:

class Book

{ public:

Book(char* s) { name = new char[strlen(s+1)];

strcpy(name, s);

}

void print() { cout << "Here is a book with name "

 

 

فصل یازدهم / ترکیب و وراثت 375

<< name << ".\n";

}

protected:

char* name;

};

class Ebook : public Book

{ public:

Ebook(char* s, float g) : Book(s), size(g) {}

void print() { cout << "Here is an Ebook with name "

<< name << " and size "

<< size << " MB.\n";

}

private:

float size;

}

class Notebook : public Book

{ public:

Notebook(char* s, int n) : Book(s) , pages(n) {}

void print() { cout << "Here is a Notebook with name "

<< name << " and " << pages

<< " pages.\n";

}

private:

int pages;

};

int main()

{ Book* b;

Book mybook("C++");

b = &mybook;

b->print();

Ebook myebook("C#", 5.16);

b = &myebook;

b->print();

Notebook mynotebook(".NET", 230);

b = &mynotebook;

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

376 برنامه سازی پیشرفته

b->print();

}

Here is a book with name C++.

Here is a book with name C#.

Here is a book with name .NET.

یک کلاس والد است که دارای دو فرزند به نام های Book در برنامۀ بالا کلاس

هستند. print() می باشد. هر سۀ این کلا سها دارای تابع Notebook و Ebook

تعریف شده، پس می توان آن را به اشیایی Book* از نوع کلاس والد یعنی b اشاره گر

از کلاس های فرزند نیز اشاره داد اما هر دفعه هنگام فراخوانی

اجرا می شود. Book از کلاس print() فقط تابع b->print()

در کلاس والد را به شکل مجازی اعلان می کنیم: print() حالا تابع

class Book

{ public:

Book(char* s) { name = new char[strlen(s+1)];

strcpy(name, s);

}

virtual void print() { cout << "Here is a book with

name " << name << ".\n";

}

protected:

char* name;

};

اکنون که با این تغییر، دوباره برنامه را اجرا کنیم، همه چیز به درستی طبق انتظار ما

پیش می رود:

Here is a book with name C++.

Here is an Ebook with name C# and size 5.16 MB.

Here is a Notebook with name .NET and pages 230.

به چه نوعی اشاره b چندریختی دارد و بسته به این که b->print() فراخوانی

داشته باشد، نتیجۀ متفاوتی خواهد داشت.

فصل یازدهم / ترکیب و وراثت 377

زمانی یک تابع را به شکل مجازی تعریف می کنند که احتمال بدهند حداقل یک

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

11 نابودکنندۀ مجازی ‐8

با توجه به تعریف توابع مجازی، به نظر می رسد که نمی توان توابع سازنده و

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

والد و فرزند، هم نام نیستند. در اصل، سازنده ها را نمی توان به شکل مجازی تعریف

کرد اما نابودگرها قصۀ دیگری دارند. مثال بعدی ایراد مهلکی را نشان می دهد که با

مجازی کردن نابودگر، برطرف می شود.

11 حافظۀ گم شده ‐ * مثال 11

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

به برنامۀ زیر دقت کنید:

 

class X

{ public:

x() { p = new int[2]; cout << "X(). "; }

~X() { delete [] p; cout << "~X().\n" }

private:

int* p;

};

class Y : public X

{ public:

Y() { q = new int[1023]; cout << "Y() : Y::q = " << q

<< ". "; }

~Y() { delete [] q; cout << "~Y(). "; }

private:

int* q;

};

int main()

{ for (int i=0; i<8; i++)

{ X* r = new Y;

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

378 برنامه سازی پیشرفته

delete r;

}

}

X(). Y() : Y::q = 0x5821c. ~X().

X(). Y() : Y::q = 0x5921c. ~X().

X(). Y() : Y::q = 0x5a21c. ~X().

X(). Y() : Y::q = 0x5b21c. ~X().

X(). Y() : Y::q = 0x5c21c. ~X().

X(). Y() : Y::q = 0x5d21c. ~X().

X(). Y() : Y::q = 0x5e21c. ~X().

X(). Y() : Y::q = 0x5f21c. ~X().

یک شیء پویای جدید ساخته می شود. طبق انتظار، سازند هها for در هر تکرار حلقۀ

با این حساب برای هر . Y() و سپس X() از بالا به پایین اجرا می شوند یعنی ابتدا

و 4092 بایت برای X شی، 4100 بایت از حافظه تخصیص می یابد ( 8 بایت برای

را احضار X معرفی شده، فقط نابودگر X به عنوان اشار هگری به اشیای r اما چون .(Y

می کند و فقط 8 بایت را آزاد می سازد و 4092 بایت باقی مانده، بلاتکلیف می مانند.

پس در هر تکرار 3992 بایت از حافظه ناپدید می شود! خروجی نیز این را تایید

را به شکل مجازی معرفی کرده و برنامه ~X() می کند. برای رفع این اشکال، نابودگر

را دوباره اجرا می نماییم:

class X

{ public:

x() { p = new int[2]; cout << "X(). "; }

virtual ~X() { delete [] p; cout << "~X().\n" }

private:

int* p;

};

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

X(). Y() : Y::q = 0x5a220. ~Y(). ~X().

 

 

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

فصل یازدهم / ترکیب و وراثت 379

هر دو نابودگر فرا خوانده می شود و در نتیجه همۀ حافظۀ for حالا هر تکرار حلقۀ

استفاده شود. r تخصیص یافته آزاد می شود و این حافظه دوباره می تواند برای اشاره گر

مثال بالا، ایراد شکاف حافظه 1 را نشان می دهد. در یک نرم افزار بزرگ، این مساله

می تواند باعث بروز فاجعه شود. مخصوصا این که پیدا کردن ایراد فوق بسیار مشکل

است. پس بخاطر داشته باشید که هر وقت از اشیای پویا در برنامه استفاده م یکنید،

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

11 کلاس های پایۀ انتزاعی ‐9

در شی گرایی رسم بر این است که ساختار برنامه و کلا سها را طوری طراحی

کنند که بتوان آن ها را به شکل یک نمودار درختی شبیه زیر نشان داد:

استفاده کنیم. شی گرایی Html برای مثال ممکن است بخواهیم در یک برنامه از کلاس

را Ebook ، را اعلان کنیم و از آن کلاس Book توصیه دارد که ابتدا کلاس پایۀ

را مشتق نماییم. گرچه ممکن است Html نیز زیرکلاس Ebook مشتق 2 کرده و از

این روش در ابتدا بی معنی و حتی وقت گیر و غیرمنطقی به نظر برسد، اما در اصل

روش مذکور سبب سهولت در اصلاح و پشتیبانی برنامه می شود. این موضوع در

برنامه های تجاری، بسیار مهم و حیاتی است.

می دانیم که در ساختار فوق، هر کلاس دارای توابع خاصی است که رفتارهای

ویژۀ آن کلاس را نشان می دهد. ممکن است توابعی مجازی هم وجود داشته باشند که

در همۀ زیرکلاس ها مغلوب شوند و نسخه ای محلی از آن ها ایجاد شود. در این حالت

دیگر نیازی نیست که توابع مذکور در کلاس های پایه دارای بدنه باشند زیرا این بدنه

BOOK

Paper BOOK EBOOK

REFERENCE MAGAZINE COOKBOOK PDF CHM HLP HTML

1 – Memory leak 2 – Derrive

 

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

380 برنامه سازی پیشرفته

هرگز به کار گرفته نمی شود. در این گونه مواقع، تابع مذکور را به شکل یک تابع

مجازی خالص 1 اعلان می کنند. یک تابع مجازی خالص، تابعی است که هیچ

پیاده سازی ندارد و فاقد بدنه است. در این توابع به جای بدنه، عبارت ; 0= را قرار

وجود print() می دهند. برای مثال، در همۀ کلاس های رابطۀ فوق، تابعی به نام

دارد که هر زیرکلاس یک نسخۀ محلی از آن را دارد. پس لازم نیست که در کلاس

برای این تابع، بدنه ای تعریف کنیم. فقط کافی است دستور Book پایۀ

virtual void print()=0;

بگنجانیم. هر وقت چنین عبارتی در بدنۀ یک کلاس ظاهر شود، Book را در کلاس

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

وجود دارد که نسخۀ محلی از آن تابع را به کار خواهد گرفت. کلاسی که یک یا چند

تابع مجازی خالص داشته باشد را کلاس پایۀ انتزاعی 2 می نامیم (به آن کلاس پایۀ

مجرد نیز گفته می شود). کلاس های پایۀ مجرد فقط برای ساختن و اشتقاق زیرکلاس ها

به کار می روند و هیچ شیئی مستقیما از روی آن ها ساخته نمی شود. کلاسی که هیچ تابع

می گوییم. اشیای داخل یک « کلاس مشتق شدۀ واقعی » مجازی خالص نداشته باشد را

برنامه از روی کلاس های مشتق شدۀ واقعی ساخته می شوند.

اگر تابع مجازی خالص اصلا فراخوانی نمی شود، پس اصلا چرا آن را اعلان می کنیم؟

پاسخ این است که تابع مجازی خالص را اعلان می کنیم تا تاکید کنیم که دست کم یک

زیرکلاس باید نسخه ای محلی از این تابع را داشته باشد.

11 کلاس پایۀ انتزاعی و یک کلاس مشتق شدۀ واقعی ‐ * مثال 12

class VCR

{ public:

virtual void on() =0;

virtual void off() =0;

virtual void record() =0;

virtual void stop() =0;

virtual void play() =0;

};

1 – Pure virtual function 2 – Abstracted base class

 

 

فصل یازدهم / ترکیب و وراثت 381

class Video : public VCR

{ public:

void on();

void off();

void record();

void stop();

void play();

};

class Camera : public VCR

{ public:

void on();

void off();

void record();

void stop();

void play();

};

Camera و Video یک کلاس پایۀ انتزاعی است که کلاس VCR در کد بالا، کلاس

همگی به شکل یک تابع مجازی خالص VCR از آن مشتق می شود. توابع عضو کلاس

نیز اعلان شد هاند که Camera و Video اعلان شده اند. این توابع در زیرکلاس

نسخه های محلی و غالب را نشان می دهند.

مثال هایی که در این فصل و دو فصل قبل دیدید خیلی کاربردی نستند و فقط

برای آموزش مفاهیم شی گرایی بیان شده اند. حالا که با شی گرایی و مزایای آن آشنا

شده اید، وقت آن رسیده که برنامه نویسی شی گرا را با جدیت دنبال کنید و تلاش داشته

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

با مشکلاتی مواحه شوید که با مرور مطالب ذکر شده خواهید توانست بر آن ها غلبه

کنید. هر چه بیشتر در شی گرایی تبحر پیدا کنید، برنامه های تجاری مطمئن ترین خواهید

نوشت و احتمال شکست در پروژ ههای گروهی که اجرا می کنید، کم تر می شود.

مسلم است که شی گرایی، رهیافت نهایی در جهان برنامه نویسی نیست و هر

چه زمان می گذرد، راهکارهای تازه ای در جهت آسان سازی برنامه نویسی پدید می آید

لیکن برنام هنویسان شی گرایی را به عنوان یک راهکار قابل اعتماد، پذیرفته اند.

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

382 برنامه سازی پیشرفته

پرسش های گزینه ای

کدام گزینه صحیح است؟ class X : public Y { } 1 – در کد

دارد Y عضوی از نوع کلاس X الف – کلاس

است Y والد کلاس X ب – کلاس

مشتق شده است X از کلاس Y ج – کلاس

دسترسی دارد Y به اعضای عمومی کلاس X د – کلاس

باشد، آنگاه: B فرزند کلاس A 2 – اگر کلاس

دسترسی دارد B به اعضای عمومی کلاس A الف – کلاس

دسترسی دارد A به اعضای عمومی کلاس B ب – کلاس

دسترسی دارد A به اعضای خصوصی کلاس B ج – کلاس

دسترسی دارد A به اعضای حفاظت شد ۀ کلاس B د – کلاس

دارای یک عضو B است. اگر کلاس B فرزند کلاس A 3 – فرض کنید کلاس

باشد آنگاه: m حفاظت شده به نام

را به شکل یک عضو خصوصی به ارث می گیرد m عضو A الف – کلاس

را به شکل یک عضو عمومی به ارث می گیرد m عضو A ب – کلاس

را به شکل یک عضو حفاظت شده به ارث می گیرد m عضو A ج – کلاس

را ندارد m اجازۀ دستیابی به عضو A د – کلاس

است و در هر دو کلاس، یک عضو عمومی B فرزند کلاس A 4 – فرض کنید کلاس

باشد، B یک شی از کلاس b و A یک شی از کلاس a اعلان شده. حال اگر x به نام

کدام گزینه صحیح است؟

عضو موروثی است a.B::x عضو غالب است و a.x – الف

عضو موروثی است b.A::x عضو غالب است و b.x – ب

عضو موروثی است a.x عضو غالب است و a.B::x – ج

عضو موروثی است b.x عضو غالب است و b.A::x – د

 

فصل یازدهم / ترکیب و وراثت 383

5 – عضو حفاظت شده عضوی است که:

الف – از خارج کلاس قابل دستیابی است

ب – فقط توسط اعضای همان کلاس قابل دستیابی است

ج – فقط توسط اعضای کلاس فرزند قابل دستیابی است

د – توسط اعضای همان کلاس و اعضای کلاس فرزند قابل دستیابی است

6 – کدام گزینه در وراثت صحیح نیست؟

الف – قبل از فراخوانی سازندۀ والد، سازندۀ فرزند فراخوانی می شود

ب – بعد از فراخوانی نابودکنندۀ فرزند، نابودکنندۀ والد فراخوانی می شود

ج – قبل از فراخوانی سازندۀ فرزند، سازندۀ والد فراخوانی می شود

د – فراخوانی سازندۀ والد ربطی به سازندۀ فرزند ندارد

7 – کدام گزینه در بارۀ چندریختی کلاس ها صحیح است؟

الف – چندریختی به وسیلۀ استفاده از توابع مجازی امکا نپذیر است

ب – چندریختی به وسیلۀ استفاده از اعضای حفاظت شده امکان پذیر است

ج – چندریختی به وسیلۀ استفاده از اشیای ثابت امکان پذیر است

د – چندریختی به وسیلۀ استفاده از توابع دستیابی امکان پذیر است

معادل کدام کد زیر است؟ p->f(); 8 – کد

p.f(); – ب *p.f(); ‐ الف

p.(*f)() – د (*p).f(); – ج

9 – کدام گزینه صحیح است؟

الف – تابع سازنده را می توان در کلاس والد به شکل مجازی تعریف کرد ولی

نابودکننده را نمی توان

ب – تابع نابودکننده را می توان در کلاس والد به شکل مجازی تعریف کرد ولی

سازنده را نمی توان

ج – هر دو تابع سازنده و نابودکننده را می توان در کلاس والد به شکل مجازی تعریف کرد

د – هیچ یک از دو تابع سازنده و نابودکننده را نمی توان در کلاس والد به شکل

مجازی تعریف کرد.

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

384 برنامه سازی پیشرفته

10 – تابع مجازی خالص تابعی است که :

الف – هیچ پیاده سازی ندارد و تعریف آن فاقد بدنه است

ب – نمی تواند توسط کلاس فرزند به ارث گرفته شود

ج – عضو هیچ کلاسی نیست

است void د – هیچ پارامتری ندارد و نوع بازگشتی آن

11 – وقتی در تعریف یک کلاس از تابع مجازی خالص استفاده شود، آنگاه:

الف – آن کلاس حداقل یک فرزند دارد

ب – در یک فرزند آن کلاس، تابع مذکور یک نسخۀ محلی دارد

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

د – هر سه مورد

12 – اگر کلاسی یک کلاس پایۀ مجرد باشد آنگاه:

الف – آن کلاس هیچ تابع مجازی خالص ندارد

ب – آن کلاس یک یا چند تابع مجازی خالص دارد

ج – آن کلاس برای اشتقاق زیرکلاس ها به کار می رود

د – گزینۀ ب و ج صحیح است.

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصل یازدهم / ترکیب و وراثت 385

پرسش های تشریحی

1‐ ترکیب چه تفاوتی با وراثت دارد ؟

دارند ؟ private چه تفاوتی با اعضای protected 2‐ اعضای

3‐ رفتار سازندۀ پیش فرض و نابودکننده در وراثت چگونه است؟

مجازی ) چیست ؟ ) virtual 4‐ تابع عضو

5‐ تابع عضو مجازی خالص چیست ؟

6‐ شکاف حافظه چگونه ایجاد می شود و برای جلوگیری از آن چه باید کرد ؟

8‐ کلاس پایۀ انتزاعی چیست و چرا ساخته می شود؟

9‐ کلاس مشتق شدۀ واقعی چیست؟

10 ‐ بسته بندی ایستا و بسته بندی پویا چه تفاوتی با هم دارد؟

12 ‐ چندریختی چیست و چگونه سبب توسعۀ کلاس می شود؟

13 ‐ چه خطایی در تعاریف زیر اس ت؟

class X

{ protected:

int a;

};

class Y : public X

{ public:

void set(X x, int c) { x.a = c; }

};

 

386 برنامه سازی پیشرفته

تمرین های برنامه نویسی

1‐ سلسله مراتب کلاس زیر را پیاده سازی کنید:

که اشیای آن شبیه شکل زیر هستند را تعریف و آزمایش کنید. سپس Name 2‐ کلاس

ایجاد کنید که مشخصات Person کلاسی به نام

افراد شامل نام، تاریخ تولد، سن و مدرک تحصیلی

را طوری Person را نگهداری کند. کلاس

تعریف کنید که برای نگهداری نام به جای نوع

استفاده کند: Name از نوع string

که اشیای آن شبیه شکل زیر هستند را تعریف و آزمایش کنید. Address 3‐ کلاس

در تمرین قبلی، آن Person به کلاس address سپس با افزودن یک عضو داده ای

را بهبود دهید.

shape

TwoDimentional ThreeDimentional

Triangle Rectangle Circle Box Cone Cylinderr Sphere

last Kaveh

first Mahmoud

nick Tehrani

name

state Tehran

country IRAN

city Tehran

address

street Azadi

 

« الف » ضمیمۀ

پاسخ نامۀ پرسش های گزینه ای

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل اول فصل دوم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل سوم

 

 

 

388 برنامه سازی پیشرفته

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل

چهارم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل

پنجم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل ششم

 

ضمیمۀ الف / پاسخ نامۀ پرسش های گزینه ای 389

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل

هفتم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل هشتم فصلم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

 

390 برنامه سازی پیشرفته

فصل دهم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

فصل

یازدهم

د ج ب

الف

1

2

3

4

5

6

7

8

9

10

 

« ب » ضمیمه

جدول اسکی

هر کاراکتر به صورت یک کد صحیح در حافظه ذخیره می شود. این کد، عددی

در محدودۀ صفر تا 127 است. به جدولی که تمام 128 کاراکتر موجود در این

می گویند. ASCII محدوده را با یک ترتیب از پیش مشخص نشان می دهد، جدول

شرح این جدول در ادامه آمده است. توجه کنید که 32 کاراکتر اول کاراکترهای

چاپ نشدنی هستند. لذا به جای نشان دادن سمبل آن ها در ستون اول، زنجیر ۀ کنترلی

آن ها یا زنجیرۀ خروجی آن ها نشان داده شده است. زنجیرۀ کنترلی یک کاراکتر غیر

با کلید دیگری است که این دو باهم فشار داده می شوند Ctrl چاپی، ترکیبی از کلید

تا کاراکتر مورد نظر وارد شود. برای مثال، کاراکتر پایان فایل (با کد اسکی 4) با زنجیرۀ

وارد می شود. زنجیرۀ خروجی یک کاراکتر غیر چاپی، ترکیبی است از Ctrl+D

C++ کاراکتر بک اسلش \ (که کاراکتر کنترل نامیده شده) و یک حرف که در کد منبع

تایپ می شود تا آن کاراکتر را مشخص کند. برای مثال کاراکتر خط جدید (با کد اسکی

نوشته می شود. \n به صورت C++ 10 ) در برنامۀ

کاراکتر شرح مبنای ده مبنای هشت مبنای شانزده

0x0 000 خالی – پایان رشته 0 Ctrl+@

0x1 001 شروع سرآیند 1 Ctrl+A

0x2 002 شروع متن 2 Ctrl+B

0x3 003 پایان متن 3 Ctrl+C

0x4 004 پایان انتقال – پایان فایل 4 Ctrl+D

0x5 005 رهایی، بیرون رفتن 5 Ctrl+E

 

392 برنامه سازی پیشرفته

کاراکتر شرح مبنای ده مبنای هشت مبنای شانزده

0x6 006 تصدیق 6 Ctrl+F

0x7 007 زنگ، بوق سیستم 7 \a

0x8 010 پسخور 8 \b

0x9 011 جدول افقی 9 \t

0xa 012 تغذیه خط، خط جدید 10 \n

0xb 013 جدول عمودی 11 \v

0xc 014 تغذیه فرم، صفحه جدید 12 \f

0xd 015 برگشت نورد 13 \r

0xe 016 شیفت(جابجایی) بیرون 14 Ctrl+N

0xf 017 شیفت داخل 15 Ctrl+O

0x10 020 پیوند داده 16 Ctrl+P

0x11 021 وسیلۀ کنترلی 1، پیمایش مجدد 17 Ctrl+Q

0x12 022 18 وسیلۀ کنترلی 2 Ctrl+R

0x13 023 وسیلۀ کنترلی 3، توقف پیمایش 19 Ctrl+S

0x14 024 20 وسیلۀ کنترلی 4 Ctrl+T

0x15 025 تصدیق منفی 21 Ctrl+U

0x16 026 بی کار کردن رخداد هم زمان 22 Ctrl+V

0x17 027 پایان بلوک انتقال 23 Ctrl+W

0x18 030 لغو 24 Ctrl+X

0x19 031 پایان پیام، وقفه 25 Ctrl+Y

0x1a 032 جانشینی، خروج 26 Ctrl+Z

0x1b 033 بیرون رفتن، رهایی 27 Ctrl+[

0x1c 034 جداساز فایل 28 Ctrl+/

0x1d 035 جداساز گروه 29 Ctrl+]

0x1e 036 جداساز رکورد 30 Ctrl+^

0x1f 037 جداساز واحد 31 Ctrl+_

 

 

ضمیمۀ ب / جدول اسکی 393

کاراکتر شرح مبنای ده مبنای هشت مبنای شانزده

0x20 040 جای خالی 32

0x21 041 ! علامت تعجب 33

0x22 042 " علامت نقل قول 34

0x23 043 # علامت شماره 35

0x24 044 $ علامت دلار 36

0x25 045 % علامت درصد 37

0x26 046 38 and & علامت

0x27 047 ' نقل قول تنها، آپستروف 39

0x28 050 ) پرانتز چپ 40

0x29 051 ( پرانتز راست 41

0x2a 052 * ضربدر، ستاره 42

0x2b 053 + بعلاوه 43

0x2c 054 , کاما، ویرگول 44

0x2d 055 - تفریق 45

0x2e 056 . نقطه، نقطه اعشار 46

0x2f 057 / اسلش 47

0x30 060 0 رقم صفر 48

0x31 061 1 رقم یک 49

0x32 062 2 رقم دو 50

0x33 063 3 رقم سه 51

0x34 064 4 رقم چهار 52

0x35 065 5 رقم پنج 53

0x36 066 6 رقم شش 54

0x37 067 7 رقم هفت 55

0x38 070 8 رقم هشت 56

0x39 071 9 رقم نه 57

394 برنامه سازی پیشرفته

کاراکتر شرح مبنای ده مبنای هشت مبنای شانزده

0x3a 072 : کولن 58

0x3b 073 ; سمیکولن 59

0x3c 074 > کوچک تر 60

0x3d 075 = مساوی 61

0x3e 076 < بزرگ تر 62

0x3f 077 ? علامت سوال 63

0x40 0100 @ علامت تجاری 64

0x41 0101 بزرگ 65 A حرف A

0x42 0102 بزرگ 66 B حرف B

0x43 0103 بزرگ 67 C حرف C

0x44 0104 بزرگ 68 D حرف D

0x45 0105 بزرگ 69 E حرف E

0x46 0106 بزرگ 70 F حرف F

0x47 0107 بزرگ 71 G حرف G

0x48 0110 بزرگ 72 H حرف H

0x49 0111 بزرگ 73 I حرف I

0x4a 0112 بزرگ 74 J حرف J

0x4b 0113 بزرگ 75 K حرف K

0x4c 0114 بزرگ 76 L حرف L

0x4d 0115 بزرگ 77 M حرف M

0x4e 0116 بزرگ 78 N حرف N

0x4f 0117 بزرگ 79 O حرف O

0x50 0120 بزرگ 80 P حرف P

0x51 0121 بزرگ 81 Q حرف Q

0x52 0122 بزرگ 82 R حرف R

0x53 0123 بزرگ 83 S حرف S

 

ضمیمۀ ب / جدول اسکی 395

کاراکتر شرح مبنای ده مبنای هشت مبنای شانزده

0x54 0124 بزرگ 84 T حرف T

0x55 0125 بزرگ 85 U حرف U

0x56 0126 بزرگ 86 V حرف V

0x57 0127 بزرگ 87 W حرف W

0x58 0130 بزرگ 88 X حرف X

0x59 0131 بزرگ 89 Y حرف Y

0x5a 0132 بزرگ 90 Z حرف Z

0x5b 0133 ] براکت چپ 91

0x5c 0134 \ بک اسلش 92

0x5d 0135 [ براکت راست 93

0x5e 0136 ^ توان 94

0x5f 0137 _ خط زیرین 95

0x60 0140 ` علامت تاکید هجا 96

0x61 0141 کوچک 97 A حرف a

0x62 0142 کوچک 98 B حرف b

0x63 0143 کوچک 99 C حرف c

0x64 0144 کوچک 100 D حرف d

0x65 0145 کوچک 101 E حرف e

0x66 0146 کوچک 102 F حرف f

0x67 0147 کوچک 103 G حرف g

0x68 0150 کوچک 104 H حرف h

0x69 0151 کوچک 105 I حرف i

0x6a 0152 کوچک 106 J حرف j

0x6b 0153 کوچک 107 K حرف k

0x6c 0154 کوچک 108 L حرف l

0x6d 0155 کوچک 109 M حرف m

 

 

396 برنامه سازی پیشرفته

کاراکتر شرح مبنای ده مبنای هشت مبنای شانزده

0x6e 0156 کوچک 110 N حرف n

0x6f 0157 کوچک 111 O حرف o

0x70 0160 کوچک 112 P حرف p

0x71 0161 کوچک 113 Q حرف q

0x72 0162 کوچک 114 R حرف r

0x73 0163 کوچک 115 S حرف s

0x74 0164 کوچک 116 T حرف t

0x75 0165 کوچک 117 U حرف u

0x76 0166 کوچک 118 V حرف v

0x77 0167 کوچک 119 W حرف w

0x78 0170 کوچک 120 X حرف x

0x79 0171 کوچک 121 Y حرف y

0x7a 0172 کوچک 122 Z حرف z

0x7b 0173 } آکولاد (ابرو) چپ 123

0x7c 0174 | خط لوله 124

0x7d 0175 { آکولاد (ابرو) راست 125

0x7e 0176 ~ علامت نقیض 126

0x7f 0177 حذف، پاک کردن 127 Delete

« ج » ضمیمه

C++ کلمات کلیدی

default

continue

const_cast

const

compl

class

char

catch

case

break

bool

bitor

bitand

auto

asm

and_eq

and

کلمه کلیدی

switch در عبارت « وگر نه » حالت

در حلقه به ابتدای دور بعدی پرش می کند

برای تغییر دادن اشیا از درون تابع عضو تغییرناپذیر استفاده می شود

تعریف یک ثابت را مشخص می کند

بیتی : ~ NOT مترادفی برای عملگر منطقی

تعریف یک کلاس را مشخص می کند

معرف نوع صحیح

فعالیت هایی را مشخص می کند که وقتی یک استثنا رخ می دهد باید اجرا شوند

شرط کنترلی را مشخص می کند switch در عبارت

را خاتمه می دهد switch یک حلقه یا عبارت

معرف نوع بولین

بیتی : | OR مترادفی برای عملگر

بیتی : & AND مترادفی برای عملگر

کلاس ذخیره سازی برای اشیایی که فقط درون بلاک خودشان ایاجد می شوند

اجازه می دهد تا اطلاعات مستقیما به اسمبلر فرستاده شود

بیتی : =& AND مترادفی برای عملگر تخصیصی

&& : AND مترادفی برای عملگر منطقی

شرح

default: sum = 0;

continue;

pp = const_cast<T*>(p)

const int s = 32;

b0 = compl b1;

class X { … };

char c;

catch(error)

case (n/10)

break;

bool flag;

b0 = b1 bitor b2;

b0 = b1 bitand b2;

auto int n;

asm ("check");

b1 and_eq b2;

(x>0 and x<8)

مثال

 

 

 

398 برنامه سازی پیشرفته

int

inline

if

goto

friend

for

float

false

extern

export

explicit

enum

else

dynamic_cast

double

do

delete

کلمه کلیدی

معرف نوع عددی صحیح

تابعی را تعریف می کند که متن آن تابع باید به جای فراخوانی آن درج شود.

ایجاد می کند if یک عبارت شرطی

باعث می شود تا اجرای برنامه به یک جملۀ برچسب دار پرش کند

در یک کلاس، تابع دوست ایجاد می کند

ایجاد می کند for یک حلقه

معرف نوع عددی حقیقی (ممیز شناور)

bool یکی از دو مقدار نوع

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

دسترسی از واحد کامپایل دیگر را ممکن می سازد

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

برای تعریف نوع شمارشی استفاده می شود

را مشخص می کند if بخش دیگر عبارت

را بر می گرداند T* برای اشاره گر داده شده، اشاره گر

نوع عددی حقیقی (ممیز شناور با دقت مضاعف)

را مشخص می کند do..while یک حلقه

تخصیص یافته آزاد می کند new حافظه ای را که با عبارت

شرح

int n;

inline int f();

if (n>0) …

goto error;

friend int f();

for ( ; ; ) …

float x;

bool flag=false;

extern int max;

export template<class T>

explicit X(int n);

enum bool {…};

else n=0;

pp = dynamic_cast<T*>p

double x;

do {…} while …

delete a;

مثال

 

399 C++ ضمیمۀ ج / کلمات کلیدی

signed

short

return

reinterpret_cast

register

public

protected

private

or_eq

or

opereator

not_eq

not

new

namespace

mutable

long

کلمه کلیدی

برای تعریف انواع صحیح علامت دار به کار می رود

معرف نوع صحیح محدود

عبارتی که تابع را خاتمه می دهد و یک مقدار را بر می گرداند

یک شی با نوع و مقدار داده شده را بر می گرداند

مشخص کننده کلاس ذخیره سازی برای اشیایی که در ثبات ها ذخیره می شوند

اعضای عمومی را در یک کلاس مشخص می کند

اعضای حفاظت شده را در یک کلاس مشخص می کند

اعضای خصوصی را در یک کلاس مشخص می کند

بیتی : =| OR مترادفی برای عملگر تخصیصی

منطقی : || OR مترادفی برای عملگر

برای تعریف سربارگذاری عملگرها به کار می رود

مترادفی برای عملگر نابرابری : =!

منطقی : ! NOT مترادفی برای عملگر

حافظه ای را تخصیص می دهد

بلوک های فضای نام (میدان) را می شناساند

به توابع تغییر ناپذیر اجازه می دهد تا فیلد را تغییر دهند

برای تعریف انواع گسترش یافته صحیح و حقیقی استفاده می شود

شرح

signed char c;

short n;

return 0;

pp = reinterpret_cast<T*>(p)

register int i;

public: int n;

protected: int n;

private: int n;

b1 or_eq b2;

(x>0 or x<8)

x operator++()

(x not_eq 0)

(not(x==0))

int* p = new int;

namespace best { int num; }

mutable string ssn;

long double x;

مثال

 

400 برنامه سازی پیشرفته

virtual

unsigned

union

using

typename

typeid

typedef

try

true

throw

this

template

switch

struct

static_cast

static

sizeof

کلمه کلیدی

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

برای تعریف انواع صحیح بدون علامت استفاده می شود

ساختاری را مشخص می کند که اجزای آن از حافظه مشترک استفاده می کنند

دستوری که اجازه می دهد تا پیشوند و فضای نام حذف شود

class مترادفی برای کلمه کلیدی

شیئی را بر می گرداند که نوع یک عبارت را نشان می دهد

برای یک نوع موجود، مترادفی را تعریف می کند

بلوکی را مشخص می کند که شامل مدیریت کننده استثنا است

bool یکی از مقادیر ممکن برای متغیرهای نوع

برای تولید یک استثنا به کار می رود

اشاره گری که به شیء جاری اشاره می کند

را مشخص می کند template یک کلاس

را مشخص می کند switch یک عبارت

تعریف یک ساختار را مشخص می کند

بر می گرداند T* برای اشاره گر داده شده یک اشاره گر

کلاس ذخیره سازی برای اشیایی که در طول اجرای برنامه وجود دارند

تعداد بایت هایی که برای ذخیره سازی یک شی استفاده شده را بر می گرداند

شرح

virtual int f();

unsigned int b;

union z { … };

using namespace std;

typename X { … };

cout << typeid(x).name();

typedef int Num;

try { … }

bool flag = true;

throw x();

return *this;

template <class t>

switch (n) { … }

struct X {…};

pp = static_cast<T*>p

static int n;

n = sizeof(float);

مثال

 

401 C++ ضمیمۀ ج / کلمات کلیدی

xor_eq

xor

while

wchar_t

volatile

void

کلمه کلیدی

انحصاری بیتی : =^ OR معادلی برای عملگر تخصیصی

انحصاری بیتی : ^ OR معادلی برای عملگر

ایجاد می کند while یک حلقه

unicode نوع کاراکتری عریض ( 16 بیتی) برای

اشیایی را تعریف می کند که می توانند خارج از کنترل برنامه تغییر داده شوند

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

شرح

b1 xor_eq b2;

b0 = b1 xor b2;

while (n > 0) …

wchar_t province;

int volatile n;

void f();

مثال

 

 

 

« د » ضمیمه

استاندارد C++ عملگرهای

با توجه به حق تقدم آ نها فهرست شده است. عملگرهای C++ در این جدول همۀ عملگرهای

با سطح تقدم بالاتر قبل از عملگرهای با سطح تقدم پایین تر ارزیابی می شوند. برای مثال در عبارت

عملگر * ابتدا ارزیابی می شود و سپس عملگر دوم یعنی – ارزیابی می گردد زیرا * در (a-b*c)

تقدم سطح 13 است که بالاتر از سطح تقدم – که 12 است می باشد.

مشخص شده، می گوید که آن عملگر از چپ ارزیابی می شود « وابستگی » ستونی که با عبارت

ارزیابی می شود زیرا – ((a-b)-c) به صورت (a-b-c) یا از راست. برای مثال عبارت

وابسته به چپ است.

مشخص شده، می گوید که آن عملگر بر روی چند عملگر عمل می کند. « جمعیت » ستونی که با

مشخص شده، می گوید که آیا عملگر قابل سربارگذاری هست یا خیر. « سربار » ستونی که با

(سربارگذاری را در فصل دهم مطالعه کنید).

عملوند نام سطح وابستگی جمعیت سربار مثال

::x :: جداسازی حوزه سراسری 17 راست یک خیر

X::x :: جداسازی حوزه کلاسی 17 چپ دو خیر

s.len . انتخاب عضو مستقیم 16 چپ دو خیر

p->len <- انتخاب عضو غیر مستقیم 16 چپ دو بله

a[i] [] جانشین معادل 16 چپ دو بله

rand() () فراخوانی تابع 16 چپ ‐‐ بله

int(ch) () ساختن انواع 16 چپ ‐‐ بله

n++ ++ پس افزایشی 16 راست یک بله

n-- -- پس کاهشی 16 راست یک بله

sizeof(a) اندازه شی یا نوع 15 راست یک خیر sizeof

 

استاندارد 403 C++ ضمیمۀ د / عملگر های

++n ++ پیش افزایشی 15 راست یک بله

--n -- پیش کاهشی 15 راست یک بله

عملوند نام سطح وابستگی جمعیت سربار مثال

~s ~ مکمل و منفی کردن 15 راست یک بله

!p منطقی 15 راست یک بله NOT !

+n + جمع بدون وابستگی 15 راست یک بله

-n - تفریق بدون وابستگی 15 راست یک بله

*p * عملگر اشاره 15 راست یک بله

&x & آدرس 15 راست یک بله

new p تخصیص حافظه 15 راست یک بله new

delete p آزاد سازی حافظه 15 راست یک بله delete

int(ch) () تبدیل نوع 15 راست دو بله

x.*q *. انتخاب عضو مستقیم 14 چپ دو خیر

p->q *<- انتخاب عضو غیر مستقیم 14 چپ دو بله

m * n * ضرب 13 چپ دو بله

m / n / تقسیم 13 چپ دو بله

m % n % باقیمانده 13 چپ دو بله

m + n + جمع 12 چپ دو بله

m - n - تفریق 12 چپ دو بله

cout << n >> تغییر جهت به چپ 11 چپ دو بله

cin >> n << تغییر جهت به راست 11 چپ دو بله

x < y > کوچک تر 10 چپ دو بله

x <= y => کوچک تر یا مساوی 10 چپ دو بله

x > y < بزرگ تر 10 چپ دو بله

x >= y =< بزرگ تر یا مساوی 10 چپ دو بله

x == y == برابری 9 چپ دو بله

x != y =! نابرابری 9 چپ دو بله

s & t 8 چپ دو بله AND & نشانه

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

404 برنامه سازی پیشرفته

S ^ t 7 چپ دو بله XOR ^ نشانه

s | t 6 چپ دو بله OR | نشانه

u && v منطقی 5 چپ دو بله AND &&

u || v منطقی 4 چپ دو بله OR ||

U ? x : y :? عبارت شرطی 3 چپ سه خیر

n = = تخصیص 2 راست دو بله 22

n += =+ جمع تخصیصی 2 راست دو بله 8

عملوند نام سطح وابستگی جمعیت سربار مثال

n -= =- تفریق تخصیصی 2 راست دو بله 4

n *= - =* ضرب تخصیصی 2 راست دو بله 1

n /= =/ تقسیم تخصیصی 2 راست دو بله 10

n %= =% باقیمانده تخصیصی 2 راست دو بله 10

s &= mask تخصیصی 2 راست دو بله AND &=

s ^= mask تخصیصی 2 راست دو بله XOR ^=

s |= mask تخصیصی 2 راست دو بله OR |=

=>> تغییر جهت به چپ

تخصیصی

s << 2 راست دو بله 1

=<< تغییر جهت به راست

تخصیصی

s >> 2 راست دو بله 1

++m, --n , کاما 0 چپ دو بله

 

« ه » ضمیمه

فهرست منابع و مأخذ

[Cline]

C++ FAQs, Second Edition, by Marshall Cline, Greg Lomow, and Mike Girou.

Addison-Wesley Publishing Company, Reading, MA (1999) 0-201-30983-1

[Deitel]

C++ How to Program, Second Edition by H. M. Deitel and P. J. Deitel.

Prentice Hall, Englewood Cliffs, NJ (1998) 0-13-528910-6.

[Hubbard1]

Foundamentals of Computing with C++, by John R. Hubbard.

McGraw-Hill, Inc, New York, NY (1998) 0-07-030868-3.

[Hubbard2]

Data Structures with C++, by John R. Hubbard.

McGraw-Hill, Inc, New York, NY (1999) 0-07-135345-3.

[Hubbard3]

Programming with C++, Second Edition, by John R. Hubbard.

McGraw-Hill, Inc, New York, NY (2000) 0-07-118372-8.

[Hughes]

Mastering the Standard C++ Classes, by Cameron Hughes and Tracey Hughes.

John Wiley & Sons, Inc, New York, NY (1999) 0-471-32893-6.

[Johnsonbaugh]

Object_Oriented Programming in C++, by Richard Johnsonbaugh and Martin Kalin.

Prentice Hall, Englewood Cliffs, NJ (1995) 0-02-360682-7.

[Perry]

An Introduction to Object-Oriented Design in C++, by Jo Ellen Perry and Harold D. Levin.

Addison-Wesley Publishing Company, Reading, MA (1996) 0-201-76564-0.

[Savitch]

Problem Solving with C++, by Walter Savitch.

Addison-Wesley Publishing Company, Reading, MA (1996) 0-8053-7440-X.

[Stroustrup1]

The C++ Programming Languages, special Edition, by Bjarne Stroustrup.

Addison-Wesley Publishing Company, Reading, MA (2000) 0-201-70073-5.

[Stroustrup2]

The Design and Evolution of C++, by Bjarne Stroustrup.

Addison-Wesley Publishing Company, Reading, MA (1994) 0-201-54330-3.

[Weiss]

Data Structures and Algorithm Analysis in C++, by Mark Allen Weiss.

Benjamin/Cummings Publishing Company, Redwood City, CA (1994) 0-8053-5443-3.

 

فهرست مطالب

فصل اول

«C++ مقدمات برنامه نویسی با »

1 ؟ C++ 1چرا ‐1

2 C++ 1 تاریخچۀ –2

1 آماده سازی مقدمات 3 –3

4 C++ 1 شروع کار با –4

1 عملگر خروجی 10 –5

1 لیترال ها و کاراکترها 11 –6

1 متغیرها و تعریف آن ها: 12 –7

1 مقداردهی اولیه به متغیرها 15 –8

1 ثابت ها 16 –9

1 عملگر ورودی 17 –10

پرسش های گزینه ای 20

پرسش های تشریحی 22

تمرین های برنامه نویسی 23

فصل دوم

« انواع اصلی »

2 انواع دادۀ عددی 25 –1

2 متغیر عدد صحیح 26 –2

2 محاسبات اعداد صحیح 28 –3

2 عملگرهای افزایشی و کاهشی 29 –4

2 عملگرهای مقدارگذاری مرکب 31 –5

2 انواع ممیز شناور 32 –6

2 تعریف متغیر ممیز شناور 33 –7

2 شکل علمی مقادیر ممیز شناور 35 –8

36 bool 2 نوع بولین –9

37 char 2 نوع کاراکتری ‐10

39 enum 2 نوع شمارشی –11

2 تبدیل نوع، گسترش نوع 42 –12

2 برخی از خطاهای برنامه نویسی 45 –13

2 سرریزی عددی 46 –14

2 خطای گرد کردن 48 –5

2 حوزۀ متغیرها 54 –6

پرسش های گزینه ای 58

پرسش های تشریحی 60

تمرین های برنامه نویسی 61

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

فصل سوم

« انتخاب »

63 if 3 دستور ‐1

65 if..else 3 دستور ‐2

3 عملگرهای مقایسه ای 66 ‐4

3 بلوک های دستورالعمل 68 ‐5

3 شرط های مرکب 71 ‐6

3 ارزیابی میانبری 73 ‐7

3 عبارات منطقی 74 ‐8

3 دستور های انتخاب تودرتو 75 ‐9

79 else if 3 ساختار ‐10

81 switch 3 دستورالعمل ‐11

3 عملگر عبارت شرطی 84 ‐12

3 کلمات کلیدی 85 ‐13

پرسش های گزینه ای 87

پرسش های تشریحی 90

تمرین های برنامه نویسی 93

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

 

فصل چهارم

« تکرار »

مقدمه 95

95 while 4 دستور ‐1

4 خاتمه دادن به یک حلقه 98 ‐2

102 do..while 4 دستور ‐3

104 for 4 دستور ‐4

110 break 4 دستور ‐5

112 continue 4 دستور ‐6

114 goto 4 دستور ‐7

4 تولید اعداد شبه تصادفی 116 ‐8

پرسش های گزینه ای 124

پرسش های تشریحی 127

تمرین های برنامه نویسی 128

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل پنجم

« توابع »

5 مقدمه 130 ‐1

استاندارد 130 C++ 5 توابع کتابخانه ای ‐2

5 توابع ساخت کاربر 135 ‐3

5 برنامۀ آزمون 136 ‐4

5 اعلان ها و تعاریف تابع 139 ‐5

5 کامپایل جداگانۀ توابع 141 ‐6

5 متغیرهای محلی، توابع محلی 143 ‐6

146 void 5 تابع ‐7

5 توابع بولی 148 ‐8

150 (I/O) 5 توابع ورودی/خروجی ‐9

5 ارسال به طریق ارجاع (آدرس) 152 ‐14

5 ارسال از طریق ارجاع ثابت 158 ‐11

5 توابع بی واسطه 160 ‐12

5 چندشکلی توابع 161 ‐13

163 main() 5 تابع ‐14

5 آرگومان های پیش فرض 165 ‐15

پرسش های گزینه ای 167

پرسش های تشریحی 170

تمرین های برنامه نویسی 170

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل ششم

« آرایه ها »

6 مقدمه 174 ‐1

6 پردازش آرایه ها 175 ‐2

6 مقداردهی آرایه ها 177 ‐3

6 ایندکس بیرون از حدود آرایه 180 ‐4

6 ارسال آرایه به تابع 183 ‐5

6 الگوریتم جستجوی خطی 187 ‐6

6 مرتب سازی حبابی 189 ‐7

6 الگوریتم جستجوی دودویی 190 ‐8

6 استفاده از انواع شمارشی در آرایه 195 ‐9

6 تعریف انواع 196 ‐10

6 آرایه های چند بعدی 199 ‐11

پرسش های گزینه ای 204

پرسش های تشریحی 208

تمرین های برنامه نویسی 208

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل هفتم

 

 

« اشاره گرها و ارجاع ها »

7 مقدمه 214 ‐1

7 عملگر ارجاع 215 ‐1

7 ارجاع ها 216 ‐2

7 اشاره گرها 218 ‐3

7 مقداریابی 219 ‐4

7 چپ مقدارها، راست مقدارها 222 ‐6

7 بازگشت از نوع ارجاع 223 ‐7

7 آرایه ها و اشاره گرها 225 ‐8

230 new 7 عملگر ‐13

232 delete 7 عملگر ‐14

7 آرایه های پویا 233 ‐9

7 اشاره گر ثابت 236 ‐10

7 آرایه ای از اشاره گرها 237 ‐11

7 اشاره گری به اشاره گر دیگر 238 ‐12

7 اشاره گر به توابع 238 ‐13

240 NULL و NUL 7‐14

پرسش های گزینه ای 242

پرسش های تشریحی 245

تمرین های برنامه نویسی 248

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصل هشتم

« استاندارد C++ رشته های کاراکتری و فایل ها در »

8 مقدمه 250 ‐1

8 مروری بر اشاره گرها 251 ‐2

252 C 8 رشته های کاراکتری در ‐3

8 ورودی /خروجی رشته های کاراکتری 253 ‐ 4

256 cout و cin 8 چند تاب ع عضو ‐5

استاندارد 261 C 8 توابع کاراکتری ‐6

8 آرایه ای از رشته ها 262 ‐7

8 توابع استاندارد رشته های کاراکتری 266 ‐8

استاندارد 275 C++ 8 رشته های کاراکتری در ‐9

8 نگاهی دقیق تر به تبادل داده ها 275 ‐10

8 ورودی قالب بندی نشده 278 ‐11

استاندارد 281 C++ در string 8 نوع ‐12

8 فایل ها 284 ‐13

پرسش های گزینه ای 290

پرسش های تشریحی 29

تمرین های برنامه نویسی 296

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصل نهم

 

« شی گرایی »

9 مقدمه 299 ‐1

9 اعلان کلاس ها 303 ‐2

9 سازنده ها 309 ‐3

9 فهرست مقداردهی در سازنده ها 312 ‐4

9 توابع دستیابی 313 ‐5

9 توابع عضو خصوصی 314 ‐6

9 سازندۀ کپی 316 ‐7

9 نابود کننده 319 ‐8

9 اشیای ثابت 321 ‐9

9 اشاره گر به اشیا 322 ‐10

9 اعضای داده ای ایستا 325 ‐11

9 توابع عضو ایستا 328 ‐12

پرسش های گزینه ای 330

پرسش های تشریحی 333

تمرین های برنامه نویسی 334

 

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصل دهم

« سربارگذاری عملگرها »

10 مقدمه 337 ‐1

10 توابع دوست 338 ‐2

10 سربارگذاری عملگر جایگزینی (=) 339 ‐3

340 this 10 اشاره گر ‐4

10 سربارگذاری عملگرهای حسابی 342 ‐5

10 سربارگذاری عملگرهای ‐6

جایگزینی حسابی 344

10 سربارگذاری عملگرهای رابطه ای 346 ‐7

10 سربارگذاری عملگرهای ‐8

افزایشی و کاهشی 347

پرسش های گزینه ای 352

پرسش های تشریحی 354

تمرین های برنامه نویسی 354

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصل یازدهم

« ترکیب و وراثت »

12 مقدمه 357 ‐1

12 ترکیب 357 ‐2

11 وراثت 361 ‐3

11 اعضای حفاظت شده 364 ‐4

11 غلبه کردن بر وراثت 367 ‐5

11 اشاره گرها در وراثت 371 ‐6

11 توابع مجازی و چندریختی 373 ‐7

11 نابودکنندۀ مجازی 377 ‐8

11 کلاس های پایۀ انتزاعی 379 ‐9

پرسش های گزینه ای 382

پرسش های تشریحی 385

تمرین های برنامه نویسی 386

ضمیمه الف : پاسخ نام ۀ پرسش های گزینه ای 383

ضمیمه ب : جدول اسکی

387

استاندارد 393 C++ ضمیمه ج : کلمات کلیدی

استاندارد 398 C++ ضمیمه د : عملگرهای

ضمیمه ه : فهرست منابع و مأخذ 401

 

 

 

mohsen_mahyar@yahoo.com

 

mo-mah.persianblog.ir

 

پایان

موفق باشید

محسن قاسمی

 

 

 

 

   + MOHSEN GHASEMI - ۱:٢٢ ‎ب.ظ ; ۱۳۸٩/٥/٢٦

فصل دهم / سربارگذاری عملگر ها در++ C

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

C++ فصل دهم / سربارگذاری عملگر ها در

نیست بلکه دوست آن است. Ratio عضو کلاس numReturn() در کد بالا تابع

برای این که یک تابع را دوست یک کلاس معرفی کنیم، آن تابع را در کلاس مذکور

در اعلان آن استفاده می کنیم. توابع دوست باید friend اعلان کرده و از کلمۀ کلیدی

قبل از اعضای عمومی و خصوصی کلاس اعلان شوند و تعریف آ نها باید خارج از

کلاس و به شکل یک تابع معمولی باشد زیرا تابع دوست، عضو کلاس نیست. توابع

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

10 سربارگذاری عملگر جایگزینی (=) ‐3

در بین عملگرهای گوناگون، عملگر جایگزینی شاید بیشترین کاربرد را داشته

باشد. هدف این عملگر، کپی کردن یک شی در شیء دیگر است. مانند سازندۀ

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

کلاس ایجاد می شود اما این تابع را می توانیم به شکل صریح درون کلاس اعلان نماییم.

Ratio 10 افزودن عملگر جایگزینی به کلاس ‐ * مثال 1

است که شامل سازندۀ پیش فرض، Ratio کد زیر یک رابط کلاس برای

سازندۀ کپی و عملگر جایگزینی می باشد:

class Ratio

{ public:

Ratio(int = 0, int = 1); // default constructor

Ratio(const Ratio&); // copy constructor

void operator=(const Ratio&); // assignment operator

// other declarations go here

private:

int num, den;

};

است و operator= ، به نحو اعلان عملگر جایگزینی دقت نمایید. نام این تابع عضو

فهرست آرگومان آن مانند سازندۀ کپی می باشد یعنی یک آرگومان منفرد دارد که از نوع

همان کلاس است که به طریقۀ ارجاع ثابت ارسال می شود. عملگر جایگزینی را

می توانیم به شکل زیر تعریف کنیم:

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

340 برنامه سازی پیشرفته

void Ratio::operator=(const Ratio& r)

{ num = r.num;

den = r.den;

}

را به درون اعضای داده ای شیئی که مالک فراخوانی r کد فوق اعضای داده ای شیء

باشند، کد Ratio دو شی از کلاس y و x این عملگر است، کپی می کند. حالا اگر

با تعاریف بالا به درستی کار می کند ولی این هنوز کافی نیست. x=y;

this 10 اشاره گر ‐4

می توانیم عملگر جایگزینی را به شکل زنجیره ای مثل زیر به کار ببریم: C++ در

x = y = z = 3.14;

قرار z اجرای کد بالا از راست به چپ صورت می گیرد. یعنی ابتدا مقدار 3.14 درون

قرار داده x درون y کپی می شود و سرانجام مقدار y درون z می گیرد و سپس مقدار

می شود. عملگر جایگزینی که در مثال قبل ذکر شد، نمی تواند به شکل زنجیره ای به کار

رود. به برهان زیر توجه کنید:

x=y=z از یک کلاس باشند و در جایگزینی z و y و x فرض کنیم سه شیء

می نویسیم. عبارت داخل x=(y=z) شرکت کنند. جایگزینی مفروض را به شکل

است. مشخص x=f(y,z) پرانتز را می توانیم یک تابع تصور کنیم. پس در حقیقت

همان تابع عملگر f باشد. چون تابع x باید دارای نوع بازگشتی از نوع f است که تابع

جایگزینی است، نتیجه می شود که عملگر جایگزینی باید یک مقدار بازگشتی از نوع

همان کلاس داشته باشد. اما این مقدار بازگشتی چیست؟ عملگر جایگزینی یک شی را

درون شیء دیگر کپی می کند و چیزی برای بازگرداندن باقی نمی ماند.

مساله را حل می کند. این اشار هگر مخفی، همیشه به شیئی اشاره this اشاره گر

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

است که به شیئی که الان مقداری در آن کپی شده this جایگزینی، همین اشار هگر

اشاره دارد. این مقدار می تواند در جایگزینی بعدی از زنجیره به کار گرفته شود. اکنون

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

فصل دهم / سربارگذاری عملگر ها 341

می توانیم عملگر جایگزینی را به شکل کامل سربارگذاری کنیم. الگوی کلی برای

به شکل زیر است: T سربارگذاری عملگر جایگزینی در کلاس مفروض

T& operator=(const T&);

به صورت زیر T همچنین الگوی کلی تعریف عملگر جایگزینی برای کلاس مفروض

است:

T& T::operator=(const T& t)

{ // assign each member datum of t to the corresponding

// member datum of the owner

return *this;

}

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

را نشان می دهد. Ratio بعدی عملگر جایگزینی سربارگذاری شدۀ کامل برای کلاس

10 سربارگذاری عملگر جایگزینی به شکل صحیح ‐ * مثال 2

class Ratio

{ public:

Ratio(int =0, int =1); // default constructor

Ratio(const Ratio&); // copy constructor

Ratio& operator=(const Ratio&); // assignment operator

// other declarations go here

private:

int num, den;

// other declarations go here

};

Ratio& Ratio::operator=(const Ratio& r)

{ num = r.num;

den = r.den;

return *this;

}

می توانند در یک جایگزینی زنجیره ای شرکت کنند: Ratio حالا اشیای کلاس

 

342 برنامه سازی پیشرفته

Ratio x, y, z(22,7);

x = y = z;

توجه داشته باشید که عمل جایگزینی با عمل مقداردهی تفاوت دارد، هر چند

هر دو از عملگر یکسانی استفاده می کنند. مثلا در کد زیر:

Ratio x(22,7); // this is an initialization

Ratio y(x); // this is an initialization

Ratio z = x; // this is an initialization

Ratio w;

w = x; // this is an assignment

سه دستور اول، دستورات مقداردهی هستند ولی دستور آخر یک دستور جایگزینی

است. دستور مقداردهی، سازندۀ کپی را فرا می خواند ولی دستور جایگزینی عملگر

جایگزینی را فراخوانی می کند.

10 سربارگذاری عملگرهای حسابی ‐5

چهار عملگر حسابی + و – و * و / در همۀ زبا نهای برنامه نویسی وجود دارند

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

اضافه کنیم تا بتوانیم با استفاده از آن ها، اشیای ساخت خودمان را در محاسبات ریاضی

به کار ببریم.

عملگرهای حسابی به دو عملوند نیاز دارند. مثلا عملگر ضرب (*) در رابطۀ زیر:

z = x*y;

با توجه به رابطۀ فوق و آن چه در بخش قبلی گفتیم، عملگر ضرب سربارگذاری شده

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

از نوع همان کلاس داشته باشد. پس انتظار داریم قالب سربارگذاری عملگر ضرب

به شکل زیر باشد: Ratio برای کلاس

Ratio operator*(Ratio x, Ratio y)

{ Ratio z(x.num*y.num, x.den*y.den);

return z;

}

 

فصل دهم / سربارگذاری عملگر ها 343

نیاز دارد. چنین تابعی نمی تواند عضوی Ratio تابع فوق به دو پارامتر از نوع کلاس

باشد باید تابع مذکور T از کلاس باشد. اگر بخواهیم تابعی عضو کلاس مفروض

داشته باشد (تحقیق کنید که چرا چنین است). از T حداکثر یک پارامتر از نوع کلاس

طرفی اگر تابعی عضو کلاس نباشد، نمی تواند به اعضای خصوصی آن کلاس دستیابی

کند. برای رفع این محدودیت ها، تابع سربارگذاری عملگر ضرب را باید به عنوان تابع

دوست کلاس معرفی کنیم. لذا قالب کلی برای سربارگذاری عملگر ضرب درون کلاس

به شکل زیر است: T مفروض

Class T

{ friend T operator*(const T&, const T&);

public:

// public members

private:

// private members

}

و از آ نجا که تابع دوست عضوی از کلاس نیست، تعریف بدنۀ آن باید خارج از

نیازی friend کلاس صورت پذیرد. در تعریف بدنۀ تابع دوست به کلمۀ کلیدی

نیست و عملگر جداسازی حوزه :: نیز استفاده نمی شود:

T operator*(const T& x, const T& y)

{ T z;

// required operations for z = x*y

return z;

}

در سربارگذاری عملگرهای حسابی + و – و / نیز از قالب های کلی فوق

استفاده می کنیم با این تفاوت که در نام تابع سربارگذاری، به جای علامت ضرب *

باید علامت عملگر مربوطه را قرار دهیم و دستورات بدنۀ تابع را نیز طبق نیاز تغییر

نشان می دهد. Ratio دهیم. مثال بعدی سربارگذاری عملگر ضرب را برای کلاس

Ratio 10 سربارگذاری عملگر ضرب برای کلاس ‐ * مثال 3

class Ratio

{ friend Ratio operator*(const Ratio&, const Ratio&);

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

344 برنامه سازی پیشرفته

public:

Ratio(int = 0, int = 1);

Ratio(const Ratio&);

Ratio& operator=(const Ratio&);

// other declarations go here

private:

int num, den;

// other declarations go here

};

Ratio operator*(const Ratio& x, const Ratio& y)

{ Ratio z(x.num * y.num , x.den * y.den);

return z;

}

int main()

{ Ratio x(22,7) ,y(-3,8) ,z;

z = x; // assignment operator is called

z.print(); cout << endl;

x = y*z; // multiplication operator is called

x.print(); cout << endl;

}

22/7

-66/56

10 سربارگذاری عملگرهای جایگزینی حسابی ‐6

به خاطر بیاورید که عملگرهای جایگزینی حسابی، ترکیبی از عملگر جایگزینی و

یک عملگر حسابی دیگر است. مثلا عملگر =* ترکیبی از دو عمل ضرب * و سپس

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

این عملگرها بر خلاف عملگرهای حسابی ساده، فقط یک عملوند دارند. پس تابع

سربارگذاری عملگرهای جایگزینی حسابی بر خلاف عملگرهای حسابی، می تواند

عضو کلاس باشد. سربارگذاری عملگرهای جایگزینی حسابی بسیار شبیه سربارگذاری

عملگر جایگزینی است. قالب کلی برای سربارگذاری عملگر =* برای کلاس مفروض

به صورت زیر است: T

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

فصل دهم / سربارگذاری عملگر ها 345

class T

{ public:

T& operator*=(const T&);

// other public members

private:

// private members

};

بدنۀ تابع سربارگذاری به قالب زیر است:

T& T::operator*=(const T& x)

{ // required operations

return *this;

}

باعث می شود که بتوانیم عملگر =* را در یک رابطۀ *this استفاده از اشاره گر

چهار عملگر جایگزینی حسابی =+ و =- و =* و =/ C++ زنجیره ای به کار ببریم. در

وجود دارد. قالب کلی برای سربارگذاری همۀ این عملگرها به شکل قالب بالا است

فقط در نام تابع به جای =* باید علامت عملگر مربوطه را ذکر کرد و دستورات بدنۀ

تابع را نیز به تناسب، تغییر داد. مثال بعدی نشان می دهد که عملگر =* چگونه برای

سربارگذاری شده است. Ratio کلاس

با عملگر =* سربارگذاری شده Ratio 10 کلاس ‐ * مثال 4

class Ratio

{ public:

Ratio(int = 0, int = 1);

Ratio& operator=(const Ratio&);

Ratio& operator*=(const Ratio&);

// other declarations go here

private:

int num, den;

// other declarations go here

};

Ratio& Ratio::operator*=(const Ratio& r)

{ num = num*r.num;

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

346 برنامه سازی پیشرفته

den = den*r.den;

return *this;

}

بدیهی است که عملگر سربارگذاری شدۀ جایگزینی حسابی باید با عملگر

هر دو از y و x سربارگذاری شدۀ حسابی معادلش، نتیجۀ یکسانی داشته باشد. مثلا اگر

باشند، آنگاه دو خط کد زیر باید نتیجۀ مشابهی داشته باشند: Ratio کلاس

x *= y;

x = x*y;

10 سربارگذاری عملگرهای رابطه ای ‐7

وجود دارد که عبارتند از: < و > و <= و => و C++ شش عملگر رابط های در

== و =! . این عملگرها به همان روش عملگرهای حسابی سربارگذاری می شوند،

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

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

است. چون نوع false است و اگر آن عبارت نادرست باشد، حاصل true حاصل

مقدار 1 و به true بولین در حقیقت یک نوع عددی صحیح است، می توان به جای

مقدار 0 را قرار داد. به همین جهت نوع بازگشتی را برای توابع false جای

قرار داده اند. قالب کلی برای int سربارگذاری عملگرهای رابطه ای، از نوع

سربارگذاری عملگر رابط های == به شکل زیر است:

class T

{ friend int operator==(const T&, const T&);

public:

// public members

private:

// private members

}

همچنین قالب کلی تعریف بدنۀ این تابع به صورت زیر می باشد:

int operator==(const T& x, const T& y)

{ // required operations to finding result

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

فصل دهم / سربارگذاری عملگر ها 347

return result;

}

یک مقدار بولین یا یک عدد صحیح قرار می گیرد. سایر result که به جای

عملگرهای رابطه ای نیز از قالب بالا پیروی می کنند.

Ratio 10 سربارگذاری عملگر تساوی (==) برای کلاس ‐ * مثال 5

class Ratio

{ friend int operator==(const Ratio&, const Ratio&);

frined Ratio operator*(const Ratio&, const Ratio&);

// other declarations go here

public:

Ratio(int = 0, int = 1);

Ratio(const Ratio&);

Ratio& operator=(const Ratio&);

// other declarations go here

private:

int num, den;

// other declarations go here

};

int operator==(const Ratio& x, const Ratio& y)

{ return (x.num * y.den == y.num * x.den);

}

b به صورت کسر Ratio چون اشیای کلاس

معادل x==y هستند، بررسی تساوی a

d بررسی

c

b

را (a*d==b*c) است که برای بررسی این تساوی می توانیم مقدار a ==

بررسی کنیم. بدنۀ تابع سربارگذاری در مثال بالا همین رابطه را بررسی می کند.

10 سربارگذاری عملگرهای افزایشی و کاهشی ‐8

عملگر افزایشی ++ و کاهشی -- هر کدام دو شکل دارند: شکل پیشوندی و

شکل پسوندی. هر کدام از این حالت ها را می توان سربارگذاری کرد. ابتدا سربارگذاری

عملگر پیش افزایشی را بررسی می کنیم. عملگر پیش کاهشی به همین صورت

سربارگذاری می شود.

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

348 برنامه سازی پیشرفته

وقتی که عملگر پیش افزایشی را همراه با یک شی به کار می بریم، یک واحد به

مقدار آن شی افزوده می شود وسپس این مقدار جدید بازگشت داده می شود. پس تابعی

که عمل سربارگذاری عملگر پیش افزایشی را انجام می دهد، مقداری از نوع همان

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

است. قالب کلی برای سربارگذاری عملگر پیش افزایشی به صورت زیر است:

class T

{ public:

T operator++();

// other public members

private:

// private members

};

قالب کلی برای سربارگذاری عملگر پیش افزایشی به شکل زیر است:

T T::operator++()

{ // required operations

return *this;

}

استفاده شده. علت هم این است که مشخص *this می بینید که این جا هم از اشاره گر

به کار رفته *this نیست چه چیزی باید بازگشت داده شود. به همین دلیل اشار هگر

تا شیئی که عمل پیش افزایش روی آن صورت گرفته، بازگشت داده شود. توجه کنید که

تعیین دستورات درون بدنه در اختیار ماست. لزوما این طور نیست که حتما مقدار 1 به

مقدار فعلی شی افزوده شود. البته طبیعت این عملگر توصیه می کند که ضابطۀ فوق را

رعایت کنیم.

Ratio 10 افزودن عملگر پیش افزایشی به کلاس ‐ * مثال 6

ارزیابی گردد، مقدار 1 به ++y باشد و عبارت Ratio یک شی از کلاس y اگر

یک عدد کسری است، افزودن مقدار 1 به این کسر اثر y افزوده می شود اما چون y

باشد. حالا داریم: y=22/ متفاوتی دارد. فرض کنید 7

7

29

7

1 22 7

7

22 =

+

+ + y = + =

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

فصل دهم / سربارگذاری عملگر ها 349

num+den آن برابر با num افزایش می یابد، در اصل مقدار عضو داد های y پس وقتی

خواهد شد:

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n) , den(d) { }

Ratio operator++();

void print() { cout << num << '/' << den << endl; }

private:

int num, den;

// other declarations go here

};

int main()

{ Ratio x(22,7), y = ++x;

cout << "y = "; y.print();

cout << ", x = "; x.print();

}

Ratio Ratio::operator++()

{ num += den;

return *this;

}

y = 29/7, x = 29/7

اکنون به بررسی عملگر پس افزایشی می پردازیم. نام تابع عملگر پیش افزایشی و

نامیده می شود. ولی می دانیم که operator++ پس افزایشی شبیه هم است. هر دو

این دو عملگر یکی نیستند. برای این که این دو تابع از هم تمیز داده شوند، فهرست

پارامترهای تابع پ سافزایشی یک پارامتر عجیب دارد. به قالب کلی برای تابع عملگر

پس افزایشی توجه کنید:

T operator++(int);

دارد در حالی که می دانیم هیچ مقدار int تابع پس افزایشی یک پارامتر از نوع

« پارامتر گنگ » صحیحی به این تابع ارسال نمی شود. این پارامتر را در اصطلاح

می گویند. تنها هدف این پارامتر، تمیز دادن تابع عملگر پ سافزایشی از تابع عملگر

پیش افزایشی است. تابع عملگر پس افزایشی یک تفاوت مهم دیگر نیز دارد: دستورات

 

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

350 برنامه سازی پیشرفته

بدنۀ آن. این دستورات باید طوری باشند که مقدار عملوند مربوطه را پس از انجام

سایر محاسبات افزایش دهند نه پیش از آن. برای درک این موضوع به مثال بعدی توجه

کنید.

Ratio 10 افزودن عملگر پس افزایشی به کلاس ‐ * مثال 7

از عملگر پس افزایشی استفاده کرده ایم. تابع این عملگر y = x++; در عبارت

قرار بگیرد، تغییر ندهد. y را قبل از این که درون x باید طوری تعریف شود که مقدار

به شیء جاری (مالک فراخوانی) اشاره دارد. کافی است *this می دانیم که اشاره گر

مقدار این اشاره گر را در یک محل موقتی ذخیره کنیم و عمل افزایش را روی آن مقدار

تغییری *this موقتی انجام داده و حاصل آن را بازگشت دهیم. به این ترتیب مقدار

قرار می گیرد: y نمی کند و پس از شرکت در عمل جایگزینی، درون

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n) , den(d) { }

Ratio operator++(); //pre-increment

Ratio operator++(int); //post-increment

void print() { cout << num << '/' << den << endl; }

private:

int num, den;

};

int main()

{ Ratio x(22,7) , y = x++;

cout << "y = "; y.print();

cout << ", x = "; x.print();

}

Ratio Ratio::operator++(int)

{ Ratio temp = *this;

num += den;

return temp;

}

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

 

فصل دهم / سربارگذاری عملگر ها 351

y = 22/7 , x = 29/7

ذکر شده ولی هیچ نامی ندارد تا operator++() پارامتر گنگ در تعریف تابع

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

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

و پ سافزایشی سربارگذاری می شوند. غیر از این ها، عملگرهای دیگری نیز مثل عملگر

خروجی (>>) ، عملگر ورودی (<<) ، عملگر اندیس ([]) و عملگر تبدیل نیز وجود

دارند که می توان آن ها را برای سازگاری برای کلاس های جدید سربارگذاری کرد.

چون این عملگرها کاربرد کمتری دارند از توضیح آن ها خودداری می کنیم. اکنون که

C++ اصول سربارگذاری عملگرها را آموختید، می توانید با مراجعه به مراجع

سربارگذاری سایر عملگرها را تحقیق کنید.

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

352 برنامه سازی پیشرفته

پرسش های گزینه ای

1 – اگر تابعی دوست یک کلاس باشد، آنگاه:

الف – آن تابع یک عضو عمومی آن کلاس است

ب – آن تابع یک عضو خصوصی آن کلاس است

ج – آن تابع یک عضو محافظت شدۀ آن کلاس است

د – آن تابع اصلا عضوی از کلاس نیست

2 – کدام گزینه در مورد توابع دوست کلاس، صحیح است؟

الف – توابع دوست کلاس فقط اجازه دارند به اعضای عمومی کلاس دستیابی کنند

ب – توابع دوست کلاس از اعضای خصوصی کلاس محسوب می شوند

ج – در تعریف توابع دوست کلاس نباید از عملگر جداسازی دامنه :: استفاده شود

د – هر کلاس فقط می تواند یک تابع دوست داشته باشد

چیست؟ *this 3 – اشاره گر

الف – یک اشاره گر مخفی است که به شیئی اشاره دارد که هم اکنون عملی روی آن

صورت گرفته

ب – یک اشاره گر مخفی است که به کلاسی اشاره دارد که هم اکنون نمونه سازی شده

ج – یک اشار هگر مخفی است که به تابعی اشاره دارد که هم اکنون فراخوانی شده

د – یک اشاره گر مخفی است که به عملگری اشاره دارد که ه ماکنون اجرا شده

4 – کدام گزینه در رابطه با سربارگذاری عملگر جایگزینی صحیح نیست؟

است operator==() ، الف – نام تابع آن

ب – تابع آن، عضوی از کلاس است

ج – اگر به طور صریح ذکر نشود، آنگاه یک نسخۀ پیش فرض به کلاس اضافه می شود

د – نوع بازگشتی آن به شکل یک ارجاع است

5 – برای این که بتوانیم اشیای یک کلاس را به شکل زنجیره ای در یک عمل حسابی

شرکت دهیم باید:

الف – تابع سربارگذاری آن عمل را به شکل عضوی از کلاس اعلان کنیم

ب – پارامتر تابع سربارگذاری آن عمل را به شکل ارجاع ثابت اعلان کنیم

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

فصل دهم / سربارگذاری عملگر ها 353

ج – نوع بازگشتی تابع سربارگذاری آن عمل را به شکل ارجاع و از نوع همان کلاس

اعلان کنیم

د – بدنۀ تابع سربارگذاری آن عمل را در فایل جداگان های قرار دهیم

6 – تابع سربارگذاری عملگر پیش افزایشی باید:

الف – عضو عمومی کلاس باشد ب – عضو خصوصی کلاس باشد

ج – دوست کلاس باشد د – به شکل تابع سودمند محلی باشد

موجود باشد. در این صورت تابع Date 7 – فرض کنید که کلاس مفروض

باید: operator<(const Date&, const Date&)

الف – عضو عمومی کلاس باشد ب – عضو خصوصی کلاس باشد

ج – دوست کلاس باشد د – تابع دستیابی باشد

موجود باشد. در این صورت تابع Person 8 – فرض کنید که کلاس مفروض

چه چیزی را سربارگذاری می کند؟ Person operator--(int);

الف – عملگر پیش کاهشی را سربارگذاری می کند

ب – عملگر پس کاهشی را سربارگذاری می کند

ج – عملگر ایندکس را سربارگذاری می کند

د – عملگر خروجی را سربارگذاری می کند

9 – تفاوت بین عملگرهای سربارگذاری شدۀ پیش افزایشی و پ سافزایشی در چیست؟

الف – تابع سربارگذاری عملگر پیش افزایشی، عضو کلاس است ولی تابع سربارگذاری

عملگر پس افزایشی عضو کلاس نیست

ب – تابع سربارگذاری عملگر پیش افزایشی دوست کلاس است ولی تابع سربارگذاری

عملگر پس افزایشی دوست کلاس نیست

ج – تابع سربارگذاری عملگر پس افزایشی پارامتر گنگ دارد ولی تابع سربارگذاری

عملگر پیش افزایشی پارامتر گنگ ندارد

دارد ولی تابع سربارگذاری *this د – تابع سربارگذاری عملگر پ سافزایشی اشاره گر

ندارد *this عملگر پیش افزایشی اشاره گر

10 – نوع بازگشتی از تابع سربارگذاری عملگرهای رابط های چیست؟

float – د double – ج char – ب int – الف

354 برنامه سازی پیشرفته

پرسش های تشریحی

چگونه استفاده می شود؟ operator 1‐ کلمۀ کلیدی

به چه چیزی اشاره می کند؟ *this 2‐ اشاره گر

را نمی توان برای توابع غیر عضو استفاده کرد؟ *this 3‐ چرا اشار هگر

را برمی گرداند؟ *this ، 4‐ چرا عملگر جایگزینی سربازگذاری شده

5‐ نتیجۀ اعلان های زیر چه تفاوتی با هم دارد ؟

Ratio y(x);

Ratio y = x;

6‐ نتیجۀ دو سطر زیر چه تفاوتی با هم دارد؟

Ratio y = x;

Ratio y; y = x;

7‐ چرا نمی توان ** را به عنوان عملگر توان سربارگذاری کرد؟

8‐ چرا عملگرها ی حسابی + و - و * و / باید به صورت توابع دوست سربارگذاری

شوند؟

10 ‐ چگونه تعریف عملگر پی شافزایشی سربارگذاری شده از عملگر پ سافزایشی

سربارگذاری شده تشخیص داده می شود؟

در پیاد هسازی عملگر پیش افزایشی بدون نام است؟ int 11 ‐ چرا آرگومان

تمرین های برنامه نویسی

را با یک سازندۀ پیش فرض، یک سازندۀ کپی، یک نابودکننده و Vector 1‐ کلاس

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

کنید. هر شی از این کلاس، یک بردار را نشان می دهد.

پیاده سازی کنید. Ratio 2‐ عملگرهای تقسیم و جمع را برای کلاس

سربارگذاری Ratio 3‐ عملگرهای حسابی پیش کاهشی و پس کاهشی را برای کلاس

کنید.

سربارگذاری Ratio 4‐ عملگرهای جایگزینی حسابی =/ و =- را برای کلاس

سربارگذاری کنید. Ratio کنید. 5‐ عملگرهای رابطه ای < و =! را برای کلاس

فصل دهم / سربارگذاری عملگر ها 355

6‐ تحقیق کنید که غیر از عملگرهای ذکر شده در این فصل، کدام عملگرها را می توان

برای یک کلاس سربارگذاری کرد. به دلخواه یکی از آن عملگرها را برای C++ در

سربارگذاری کنید. Ratio کلاس

مسألۀ 3 فصل 9) عملگرهای حسابی + و – و همچنین ) Time 7‐ برای کلاس

عملگرهای رابطه ای == و > و < را سربارگذاری کنید.

مسألۀ 6 فصل 9) عملگرهای حسابی – و * را ) Matrix 8 – برای کلاس

سربارگذاری کنید.

مسألۀ 7 فصل 9) عملگرهای حسابی + و / را ) Point 9 – برای کلاس

سربارگذاری کنید.

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

 

   + MOHSEN GHASEMI - ۱٢:٢٦ ‎ق.ظ ; ۱۳۸٩/٥/٢٥

فصل نهم شی گرایی »در «++ C

mo-mah.persianblog.ir

mohsen_mahyar@yahoo.com

فصل نهم

 

C++ در « شی گرایی »

9 مقدمه ‐1

اولین نر م افزار برای نخستین رایانه ها، زنجیره ای از صفر و یک ها بود که فقط عدۀ

اندکی از این توالی سر در می آوردند. به تدریج کاربرد رایانه گسترش یافت و نیاز بود

تا نرم افزارهای بی شتری ایجاد شود. برای این منظور، برنامه نویسان مجبور بودند با

انبوهی از صفر ها و یک ها سر و کله بزنند و این باعث می شد مدت زیادی برای تولید

یک نرم افزار صرف شود. از این گذشته، اگر ایرادی در کار برنامه یافت می شد، پیدا

جهش « زبان اسمبلی 1 » کردن محل ایراد و رفع آن بسیار مشکل و طاقت فرسا بود. ابداع

بزرگی به سوی تولید نرم افزارهای کارآمد بود.

اسمبلی قابل فهم تر بود و دنبال کردن برنامه را سهولت می بخشید. سخت افزار به

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

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

1 – Assembly300 برنامه سازی پیشرفته

برای یک جمع ساده به معنای ده ها هزار خط کد برای یک برنامۀ حسابداری روزانه

دروازه های « زبان های سطح بالا » . است. این بار انبوه کدهای اسمبلی مشکل ساز شدند

تمدن جدید در دنیای نرم افزار را به روی برنامه نویسان گشودند.

زبان های سطح بالا دو نشان درخشان از ادبیات و ریاضیات همراه خود آوردند:

اول دستوراتی شبیه زبان محاوره ای که باعث شدند برنامه نویسان از دست کدهای

که سرعت تولید و « تابع » تکراری و طویل اسمبلی خلاص شوند و دوم مفهوم

عیب یابی نرم افزار را چندین برابر کرد. اساس کار این گونه بود که وظیفۀ اصلی

برنامه به وظایف کوچ کتری تقسیم می شد و برای انجام دادن هر وظیفه، تابعی نوشته

می شد. پس این ممکن بود که توابع مورد نیاز یک برنامه به طور هم زمان نوشته و

آزمایش شوند و سپس همگی در کنار هم چیده شوند. دیگر لازم نبود قسمتی از

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

می گرفت و به سرعت محل خطا یافت شده و اصلاح می شد. علاوه بر این، برای بهبود

دادن نر مافزار موجود یا افزودن امکانات اضافی به آن، دیگر لازم نبود که برنامه از نو

نوشته شود؛ فقط توابع مورد نیاز را تولید کرده یا بهبود می دادند و آن را به برنامۀ

موجود پیوند می زدند. از این به بعد بود که گروه های تولید نرم افزاری برای تولید

نرم افزارهای بزرگ ایجاد شدند و بحث مدیریت پروژ ههای نرم افزاری و شیوه های تولید

نرم افزار و چرخۀ حیات و ... مطرح شد.

نرم افزارهای بزرگ، تجربیات جدیدی به همراه آوردند و برخی از این تجربیات

نشان می داد که توابع چندان هم بی عیب نیستند. برای ایجاد یک نرم افزار، توابع زیادی

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

خروجی یک تابع تغییر کند، سایر توابعی که با تابع مذکور در ارتباط بودند نیز باید

شناسایی می شدند و به تناسب تغییر می نمودند. این موضوع، اصلاح نرم افزارها را

مشکل می کرد. علاوه بر این اگر تغییر یک تابع مرتبط فراموش می شد، صحت کل

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

بنابراین باز هم متخصصین به فکر راه چاره افتادند. پس از ریاضی و ادبیات، این بار

نوبت فلسفه بود.

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصلم / شی گرایی 301

رهیافت جدیدی بود که برای مشکلات بالا راه حل داشت. این « شی گرایی 1 »

مضمون از دنیای فلسفه به جهان برنامه نویسی آمد و کمک کرد تا معضلات تولید و

پشتیبانی نرم افزار کم تر شود. در دنیای واقعی، یک شی چیزی است که مشخصاتی دارد

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

مثلا در برابر نیروی جاذبه یا تابش نور یا وارد کردن فشار واکنش نشان می دهد. اشیا را

می توان با توجه به مشخصات و رفتار آن ها دسته بندی کرد. برای نمونه، می توانیم همۀ

قرار دهیم و همۀ « جانداران » هستند را در دست های به نام « تنفس » اشیایی که دارای رفتار

بگذاریم. بدیهی « جامدات » اشیایی که چنین رفتاری را ندارند در دستۀ دیگری به نام

است که اعضای هر دسته را می توانیم با توجه به جزییات بیشتر و دقیق تر به زیر

و « گیاهان » دسته هایی تقسیم کنیم. مثلا دستۀ جانداران را می توانیم به زیر دسته های

بخش بندی کنیم. البته هر عضو از این دسته ها، علاوه بر این که « انسان ها » و « جانوران »

مشخصاتی مشابه سایر اعضا دارد، مشخصات منحصر به فردی نیز دارد که این تفاوت

باعث می شود بتوانیم اشیای همگون را از یکدیگر تفکیک کنیم. مثلا هر انسان دارای

نام، سن، وزن، رنگ مو، رنگ چشم و مشخصات فردی دیگر است که باعث می شود

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

می گویند و به نمونه های هر کلاس « کلاس 2 » در بحث شی گرایی به دست هها

می نامند و به رفتارهای هر شی « صفت 4 » گفته می شود. مشخصات هر شی را « شی 3 »

می گویند. درخت سرو یک شی از کلاس درختان است که برخی از صف تهای « متد 5 »

آن عبارت است از: نام، طول عمر، ارتفاع، قطر و ... و برخی از متدهای آن نیز عبارتند

از: غذا ساختن، سبز شدن، خشک شدن، رشد کردن، ... .

اما این شی گرایی چه گرهی از کار برنام هنویسان می گشاید؟ برنام هنویسی شی گرا

بر سه ستون استوار است:

الف. بسته بندی 6: یعنی این که داده های مرتبط، با هم ترکیب شوند و جزییات

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

1 – Object orienting 2 – Class 3 – Object

4 – Attribute 5 – Method 6 – Encapsulation

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

302 برنامه سازی پیشرفته

کردن برنامه راح تتر صورت می گیرد و تغییر در یک بخش از برنامه، سایر بخش ها را

نیز می گویند « تجرید 1 » دچار اختلال نمی کند. مخفی کردن جزییات پیاده سازی که به آن

سبب می شود که امنیت کد حفظ شود و بخش های بی اهمیت یک فرایند از دید

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

مورد نیاز را ببیند و نمی تواند به اطلاعات نامربوط دسترسی داشته باشد و آ نها را

به جای « محصورسازی » یا « کپسوله کردن » دست کاری کند. در برخی از کتا بها از واژۀ

بسته بندی استفاده شده.

ب. وراثت 2: در دنیای واقعی، وراثت به این معناست که یک شی وقتی متولد

می شود، خصوصیات و ویژگی هایی را از والد خود به همراه دارد هرچند که این شیء

جدید با والدش در برخی از جزییات تفاوت دارد. در برنامه نویسی نیز وراثت به همین

معنا به کار می رود. یعنی از روی یک شیء موجود، شیء جدیدی ساخته شود که

صفات و متدهای شیء والدش را دارا بوده والبته صفات و متدهای خاص خود را نیز

داشته باشد. امتیاز وراثت در این است که از کدهای مشترک استفاده می شود و علاوه

بر این که می توان از کدهای قبلی استفاده مجدد کرد، در زمان نیز صرفه جویی شده و

استحکام منطقی برنامه هم افزایش می یابد.

ج. چند ریختی 3: که به آن چندشکلی هم می گویند به معنای یک چیز بودن و

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

هر فرزندی مثل والدش اثر انگشت دارد، ولی اثر انگشت هر شخص با والدش یا هر

شخص دیگر متفاوت است. پس اثر انگشت در انسان ها چندشکلی دارد.

در ادامه به شکل عملی خواهیم دید که چگونه می توانیم مفاهیم فوق را در قالب

برنامه پیاده سازی کنیم.

در برنام هنویسی، یک کلاس را می توان آرایه ای تصور کرد که اعضای آن از انوع

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

شی نیز متغیری است که از نوع یک کلاس است. به طور کلی یک شی را می توان

موجودیت مستقلی تصور کرد که داده های خاص خودش را نگهداری می کند و توابع

1 – Abstraction 2 – Inheritance 3 – Polymorphism

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 303

خاص خودش را دارد. تعاریف کلاس مشخص می کند شیئی که از روی آن کلاس

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

باید کلاس های مورد نیاز را مشخص و تعریف کنیم . سپس می توانیم در برنامۀ اصلی،

اشیایی از نوع این کلاس ها اعلان نماییم. بقیۀ برنامه را این اشیا پیش می برند.

9 اعلان کلاس ها ‐2

کد زیر اعلان یک کلاس را نشان می دهد. اشیایی که از روی این کلاس ساخته

می شوند، اعداد کسری (گویا) هستند:

class Ratio

{ public:

void assign(int, int);

viod print();

private:

int num, den;

};

شروع می شود، سپس نام کلاس می آید و اعلان class اعلان کلاس با کلمۀ کلیدی

اعضای کلاس درون یک بلوک انجام می شود و سرانجام یک سمیکولن بعد از بلوک

نشان می دهد که اعلان کلاس پایان یافته است. کلاسی که در کد بالا اعلان شده،

نام دارد. می توانیم تشخیص بدهیم که در بلوک این کلاس دو تابع و دو متغیر Ratio

را تابع عضو 1 می گوییم زیرا آن ها print() و assign() اعلان شده است. توابع

نیز گفته شده است. « سرویس » یا « متد » ، عضو این کلاس هستند. به توابع عضو

را نیز دادۀ عضو 2 می گوییم. به غیر از توابع و داد ههای عضو، den و num متغیرهای

هر . private و عبارت public دو عبارت دیگر نیز به چشم می خورد: عبارت

محسوب می شود « عضو عمومی 3 » اعلان شود، یک public عضوی که ذیل عبارت

محسوب « عضو خصوصی 4 » اعلان شود، یک private و هر عضوی که ذیل عبارت

می شود. تفاوت اعضای عمومی با اعضای خصوصی در این است که اعضای عمومی

1 – Function member 2 – Data member

3 – Public member 4 – Private member

 

304 برنامه سازی پیشرفته

کلاس در خارج از کلاس قابل دستیابی هستند اما اعضای خصوصی فقط در داخل

« مخفی سازی اطلاعات » همان کلاس قابل دستیابی هستند. این همان خاصیتی است که

و متغیرها به صورت public را ممکن می نماید. در کلاس فوق، توابع به شکل

مشخص شد هاند. private

حال ببینیم که چطور می توانیم از کلا سها در برنامۀ واقعی استفاده کنیم. به مثال

زیر دقت کنید.

Ratio 9 پیاده سازی کلاس ‐ * مثال 1

class Ratio

{ public:

void assign(int, int);

void print();

private:

int num, den;

};

int main()

{ Ratio x;

Ratio y;

x.assign(13, 7);

y.assign(19,5);

cout << "x = ";

x.print();

cout << endl;

cout << "y = ";

y.print();

cout << endl;

}

void Ratio::assign(int numerator, int denumirator)

{ num = numerator;

den = denumirator;

}

فصلم / شی گرایی 305

void Ratio::print()

{ cout << num << '/' << den;

}

x = 13/7

y = 19/5

اعلان شده. سپس در برنامۀ اصلی دو متغیر Ratio در برنامۀ بالا، ابتدا کلاس

اعلان شده اند. به متغیری که از نوع یک کلاس باشد Ratio از نوع y و x به نام های

داریم. هر یک از این y و x می گوییم. پس در برنامۀ بالا دو شی به نا مهای « شی » یک

اشیا دارای دو دادۀ خصوصی مخصوص به خود هستند و همچنین توانایی دستیابی به

دو تابع عضو عمومی را نیز دارند. این دو شی را

می توان مانند شکل مقابل تصور نمود.

موجب x.assign( عبارت ;( 13,7

برای شیء assign() می شود که تابع عضو

فراخوانی شود. توابع عضو کلاس را فقط به این طریق می توان فراخوانی کرد یعنی x

ابتدا نام شی و سپس یک نقطه و پس از آن، تابع عضو مورد نظر. در این صورت، شیء

x شیء x.assign( مذکور را مالک 1 فراخوانی می نامیم. در عبارت ;( 13,7

مالک فراخوانی تابع عضو

است و این تابع assign()

عملیاتی انجام می x روی شیء

دهد. تصویر مقابل این موضوع را

بیان می کند.

در خطوط انتهایی برنامه آمده print() و assign() تعریف دو تابع عضو

به همراه عملگر جداسازی دامنه :: قبل از نام هر تابع ذکر شده Ratio اما نام کلاس

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

هستند و از قوانین آن کلاس پیروی می کنند. Ratio

9 را تفسیر کنیم. ابتدا کلاس ‐ با توجه به توضیحات بالا، می توانیم برنامۀ مثال 1

num

den

13

7

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

Ratio Ratio

num

den

13

7

y

assign()

print()

Ratio

num

den

13

7

Ratio

x

1 – Owner

 

306 برنامه سازی پیشرفته

از روی این کلاس ساخته y و x اعلان شده است. در برنامۀ اصلی دو شیء Ratio

هستند. با den و num شده که هر کدام دارای دو عضو دادۀ خصوصی به نا مهای

مقادیر 7 و 13 به ترتیب درون اعضای خصوصی x.assign( فراخوانی ;( 13,7

مقادیر y.assign( قرار می گیرد. با فراخوانی ;( 19,5 x از شیء den و num

قرار می گیرد. y از شیء den و num 19 و 5 به ترتیب درون اعضای خصوصی

مقادیر اعضای خصوصی y.print(); و x.print(); سپس با فراخوانی

کاملا از y و x در خروجی چاپ می شود. دقت کنید که دو شیء y و شیء x شیء

یکدیگر مجزا هستند و هر کدام داده های خاص خود را دارد.

از اعضای خصوصی هستند، نمی توانیم درون den و num چون متغیرهای

و assign() برنامۀ اصلی به آن ها مستقیما دستیابی کنیم. این کار فقط از طریق توابع

میسر است زیرا این توابع عضوی از کلاس هستند و می توانند به اعضای print()

خصوصی همان کلاس دستیابی کنند.

که در بالا اعلان شد، کارایی زیادی ندارد. می توانیم با افزودن Ratio کلاس

توابع عضو دیگری، کارایی این کلاس را بهبود دهیم.

Ratio 9 افزودن توابع عضو بیشتر به کلاس ‐ * مثال 2

class Ratio

{ public:

void assign(int, int);

double convert();

void invert();

void print();

private:

int num, den;

};

int main()

{ Ratio x;

x.assign(22, 7);

cout << "x = ";

x.print();

فصلم / شی گرایی 307

cout << " = " << x.convert() << endl;

x.invert();

cout << "1/x = "; x.print();

cout << endl;

}

void Ratio::assign(int numerator, int denumirator)

{ num = numerator;

den = denumirator;

}

double Ratio::convert()

{ return double(num)/den;

}

void Ratio::invert()

{ int temp = num;

num = den;

den = temp;

}

void Ratio::print()

{ cout << num << '/' << den;

}

x = 22/7 = 3.14286

1/x = 7/22

کارایی اشیای کلاس invert() و convert() در مثال بالا با افزودن توابع عضو

بهبود یافته است. این دو تابع عضو نیز به صورت اعضای عمومی تعریف Ratio

عدد convert() شده اند تا بتوان در برنامۀ اصلی به آن ها دستیابی داشت. تابع

نیز invert() کسری درون شیء مالک را به یک عدد اعشاری تبدیل می کند و تابع

عدد کسری درون شیء مالک را معکوس می نماید.

می بینید که به راحتی می توانیم قابلیت های یک برنامۀ شی گرا را بهبود یا تغییر

دهیم بدون این که مجبور باشیم تغییرات اساسی در برنامۀ قبلی ایجاد نماییم.

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

308 برنامه سازی پیشرفته

تعریف public را نیز به صورت den و num می توانستیم اعضای داده ای

کنیم تا بتوانیم درون برنامۀ اصلی به صورت مستقیم به این اعضا دستیابی کنیم اما اصل

پنهان سازی اطلاعات این امر را توصیه نمی کند. این اصل می گوید که تا حد امکان

داده های یک کلاس را به صورت خصوصی تعریف کنید و دستیابی به آن ها را به توابع

عضو عمومی واگذار نمایید. به این ترتیب داد ههای اشیا از دید سایرین مخفی می شوند

و از تغییرات ناخواسته در امان می مانند.

به شکل خودکفا Ratio 9 اعلان کلاس ‐ * مثال 3

را نشان می دهد که تعریف توابع عضو نیز درون Ratio کد زیر، اعلان کلاس

همان کلاس قرار گرفته است:

class Ratio

{ public:

void assign(int n, int d) { num = n; den = d; }

double convert() { return double(num)/den; }

void invert() { int temp = num; num = den; den = temp;}

void print() { cout << num << '/' << den; }

private:

int num, den;

};

9 مقایسه نمایید. در اعلان فوق، ‐ در مثال 2 Ratio اعلان فوق را با اعلان کلاس

همۀ تعاریف مورد نیاز درون خود کلاس آمده است و دیگر احتیاجی به عملگر

9 باشد ‐ جداسازی دامنه :: نیست. ممکن است اعلان مذکور خواناتر از اعلان مثال 2

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

جداسازی دامنه و تعریف های خارج از کلاس برای توابع عضو استفاده کنند. در

حقیقت بدنۀ توابع اغلب در فایل جداگانه ای قرار می گیرد و به طور مستقل کامپایل

می شود. این با اصل پنهان سازی اطلاعات همسویی بیشتری دارد. در پروژه های گروهی

تولید نرم افزار، معمولا پیاده سازی کلاس ها به عهدۀ مفسرین است و استفاده از کلاس ها

در برنامۀ اصلی بر عهدۀ برنامه نویسان گذاشته می شود. برنامه نویسان فقط مایلند بدانند

که کلاس ها چه کارهایی می توانند بکنند و اصلا علاق های ندارند که بدانند کلا سها

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 309

چطور این کارها را انجام می دهند (نباید هم بدانند). برای مثال برنامه نویسان می دانند در

دستور تقسیم یک عدد اعشاری بر یک عدد اعشاری دیگر، حاصل چه خواهد بود اما

نمی دانند که عمل تقسیم چگونه انجام می شود و از چه الگوریتمی برای محاسبه پاسخ

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

ندارند و این مطالب اصلا برای آ نها اهمیت ندارد. فقط کافی است از صحیح بودن

نتیجه مطمئن باشند. با رعایت کردن اصل پنهان سازی اطلاعات، هم تقسیم کارها بین

افراد گروه بهتر انجام می شود و هم از درگیرکردن برنامۀ اصلی با جزئیات نامربوط

اجتناب شده و ساختار منطقی برنامه مستحکم تر می شود.

هنگامی که تعاریف از اعلان کلاس جدا باشد، به بخش اعلان کلاس رابط

کلاس 1 گفته می شود و به بخش تعاریف پیاده سازی 2 می گویند. رابط کلاس بخشی

است که در اختیار برنامه نویس قرار می گیرد و پیاده سازی در فایل مستقلی نگهداری

می شود.

9 سازنده ها ‐3

برای assign() 9 اعلان شد از تابع ‐ که در مثال 1 Ratio کلاس

Ratio مقداردهی به اشیای خود استفاده می کند. یعنی پس از اعلان یک شی از نوع

را برای آن شی فرا بخوانیم تا بتوانیم مقادیری را به اعضای assign() باید تابع

float و int داده ای آن شی نسبت دهیم. هنگام استفاده از انواع استاندارد مثل

می توانیم هم زمان با اعلان یک متغیر، آن را مقداردهی اولیه کنیم مثل :

int n=22;

float x=33.0;

نیز به همین شیوه مقداردهی اولیه Ratio منطقی تر خواهد بود اگر بتوانیم برای کلاس

این امکان را فراهم کرده که برای مقداردهی اولیه به اشیای یک C++ . تدارک ببینیم

کلاس، از تابع خاصی به نام تابع سازنده 3 استفاده شود. تابع سازنده یک تابع عضو

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

1 – Interface 2 - Implementation 3 – Constructor Function

 

310 برنامه سازی پیشرفته

با نام کلاس یکسان باشد و بدون نوع بازگشتی تعریف شود. مثال زیر نشان می دهد که

از یک تابع سازنده استفاده کنیم. assign() چطور می توانیم به جای تابع

Ratio 9 ایجاد تابع سازنده برای کلاس ‐ * مثال 4

class Ratio

{ public:

Ratio(int n, int d) { num = n; den = d; }

void print() { cout << num << '/' << den; }

private:

int num, den;

};

int main()

{ Ratio x(13,7) , y(19,5);

cout << "x = ";

x.print();

cout << "and y = ";

y.print();

}

x = 13/7 and y = 19/5

اعلان شد، تابع سازنده به طور خودکار فراخوانی x در کد بالا به محض این که شیء

آن ارسال می شود. تابع این مقادیر را به d و n شده و مقادیر 13 و 7 به پارامترهای

تخصیص می دهد. لذا اعلان den و num اعضای داده ای

Ratio x(13,7), y(19,5);

9 معادل است: ‐ با خطوط زیر از مثال 1

Ratio x, y;

x.assign(13,7);

y.assign(19,5);

وظیفۀ تابع سازنده این است که حافظۀ لازم را برای شیء جدید تخصیص داده

و آن را مقداردهی نماید و با اجرای وظایفی که در تابع سازنده منظور شده، شیء

جدید را برای استفاده آماده کند.

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 311

هر کلاس می تواند چندین سازنده داشته باشد. در حقیقت تابع سازنده می تواند

5 را ببینید). این سازند هها، از طریق فهرست ‐ چندشکلی داشته باشد (بخش 13

پارامترهای متفاوت از یکدیگر تفکیک می شوند. به مثال بعدی نگاه کنید.

Ratio 9 افزودن چند تابع سازندۀ دیگر به کلاس ‐ * مثال 5

class Ratio

{ public:

Ratio() { num = 0; den = 1; }

Ratio(int n) { num = n; den = 1; }

Ratio(int n, int d) { num = n; den = d; }

void print() { cout << num << '/' << den; }

private:

int num, den;

};

int main()

{ Ratio x, y(4), z(22,7);

cout << "x = ";

x.print();

cout << "\ny = ";

y.print();

cout << "\nz = ";

z.print();

}

x = 0/1

y = 4/1

z = 22/7

سه سازنده دارد: اولی هیچ پارامتری ندارد و شیء اعلان Ratio این نسخه از کلاس

شده را با مقدار پیش فرض 0 و 1 مقداردهی می کند. دومین سازنده یک پارامتر از نوع

دارد و شیء اعلان شده را طوری مقداردهی می کند که حاصل کسر با مقدار آن int

9 است. ‐ پارامتر برابر باشد. سومین سازنده نیز همان سازندۀ مثال 4

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

312 برنامه سازی پیشرفته

یک کلاس می تواند سازنده های مختلفی داشته باشد. ساده ترین آن ها، سازنده ای

است که هیچ پارامتری ندارد. به این سازنده سازندۀ پیش فرض 1 می گویند. اگر در یک

کلاس، سازندۀ پیش فرض ذکر نشود، کامپایلر به طور خودکار آن را برای کلاس مذکور

9 که سازندۀ پیش فرض منظور نکرده ایم، یکی به طور ‐ ایجاد می کند. در مثال 1

خودکار برای آن کلاس منظور خواهد شد.

9 فهرست مقداردهی در سازنده ها ‐4

سازنده ها اغلب به غیر از مقداردهی داده های عضو یک شی، کار دیگری انجام

یک واحد دستوری مخصوص پیش بینی شده که تولید C++ نمی دهند. به همین دلیل در

سازنده را تسهیل می نماید. این واحد دستوری فهرست مقداردهی 2 نام دارد.

9 دقت کنید. این سازنده را می توانیم با استفاده از ‐ به سومین سازنده در مثال 5

فهرست مقداردهی به شکل زیر خلاصه کنیم:

Ratio(int n, int d) : num(n), den(d) { }

در دستور بالا، دستورالعمل های جایگزینی که قبلا در بدنۀ تابع سازنده قرار داشتند،

اکنون درون فهرست مقداردهی جای داده شده اند (فهرست مقداردهی با حروف تیره تر

نشان داده شده). فهرست مقداردهی با یک علامت کولن : شروع می شود، بدنۀ تابع

Ratio نیز در انتها می آید (که اکنون خالی است). در مثال بعدی، سازنده های کلاس

را با فهرست مقداردهی خلاصه کرده ایم.

Ratio 9 استفاده از فهرست مقداردهی در کلاس ‐ * مثال 6

class Ratio

{ public:

Ratio() : num(0) , den(1) { }

Ratio(int n) : num(n) , den(1) { }

Ratio(int n, int d) : num(n), den(d) { }

private:

int num, den;

};

1 – Default constructor 2 – Initializing list

 

فصلم / شی گرایی 313

سازنده ها را می توانیم از این هم ساد هتر کنیم. می توانیم با استفاده از پارامترهای

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

Ratio 9 به کار گیری پارامترهای پیش فرض در سازندۀ کلاس ‐ * مثال 7

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n), den(d) { }

private:

int num, den;

};

int main()

{ Ratio x, y(4), z(22,7);

}

4 و / برابر با 1 y 0 و شیء / برابر با 1 x در این مثال وقتی که برنامه اجرا شود، شیء

22 خواهد شد. / برابر با 7 z شیء

5 گفتیم که وقتی پارامترهای واقعی به تابع ارسال نشود، به ‐ قبلا در بخش 15

n جای آن ها مقادیر پیش فرض در تابع به کار گرفته می شوند. در مثال بالا، پارامتر

از x دارای مقدار پیش فرض 1 است. وقتی شیء d دارای مقدار پیش فرض 0 و پارامتر

و x.n و بدون هیچ پارامتری اعلان می شود، این مقادیر پیش فرض به Ratio نوع

خواهد بود. هنگامی که x.den= و 1 x.num= تخصیص می یابند. بنابراین 0 x.d

خواهد شد ولی چون y.num= فقط با مقدار ارسالی 4 اعلان می شود، 4 y شیء

قرار می گیرد. y.den ذکر نشده، مقدار پیش فرض 1 در y پارامتر دوم در اعلان شیء

با دو پارامتر ارسالی 22 و 7 اعلان شده. پس در این شی مقادیر پیش فرض z شیء

برابر با 7 خواهد شد. z.den برابر با 22 و z.num نادیده گرفته شده و

9 توابع دستیابی ‐5

اعلان (private) داده های عضو یک کلاس معمولا به صورت خصوصی

می شوند تا دستیابی به آ نها محدود باشد اما همین امر باعث می شود که نتوانیم در

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

314 برنامه سازی پیشرفته

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

توابع دستیابی 1 استفاده می کنیم. تابع دستیابی یک تابع عمومی عضو کلاس است و به

همین دلیل اجازۀ دسترسی به اعضای داده ای خصوصی را دارد. از طرفی توابع دستیابی

را طوری تعریف می کنند که فقط مقدار اعضای داده ای را برگرداند ولی آن ها را تغییر

ندهد. به بیان ساده تر، با استفاده از توابع دستیابی فقط می توان اعضای داده ای خصوصی

را خواند ولی نمی توان آن ها را دس تکاری کرد.

Ratio 9 افزودن توابع دستیابی به کلاس ‐ * مثال 8

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n) , den(d) { }

int numerator() { return num; }

int denomerator() { return den; }

private:

int num, den;

};

int main()

{ Ratio x(22,7);

cout << x.numerator() << '/' << x.denumerator() << endl;

}

مقادیر موجود در داد ههای denumerator() و numerator() در این جا توابع

عضو خصوصی را نشان می دهند.

9 توابع عضو خصوصی ‐6

تاکنون توابع عضو را به شکل یک عضو عمومی کلاس اعلان کردیم تا بتوانیم در

برنامۀ اصلی آن ها را فرا بخوانیم و با استفاده از آ نها عملیاتی را روی اشیا انجام دهیم.

توابع عضو را گاهی می توانیم به شکل یک عضو خصوصی کلاس معرفی کنیم. واضح

است که چنین تابعی از داخل برنامۀ اصلی به هیچ عنوان قابل دستیابی نیست. این تابع

1 – Access function

 

فصلم / شی گرایی 315

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

تابع سودمند 1 محلی می گوییم.

9 استفاده از توابع عضو خصوصی ‐ * مثال 9

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n), den(d) { }

void print() { cout << num << '/' << den << endl; }

void printconv() { cout << toFloat() << endl; }

private:

int num, den;

double toFloat();

};

double Ratio::toFloat()

{ // converts Rational number to Float

return num/den;

}

int main()

{ Ratio x(5, 100);

x.print();

x.printconv();

}

5/100

0.05

toFloat() دارای یک تابع عضو خصوصی به نام Ratio در برنامۀ بالا، کلاس

است. وظیفۀ تابع مذکور این است که معادل ممیز شناور یک عدد کسری را برگرداند.

استفاده شده و به انجام وظیفۀ printconv() این تابع فقط درون بدنۀ تابع عضو

آن کمک می نماید و هیچ نقشی در برنامۀ اصلی ندارد. یادآوری می کنیم که چون تابع

toFloat() عضوی از کلاس است، می تواند به تابع خصوصی printconv()

دستیابی داشته باشد.

1 – Utility function

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

316 برنامه سازی پیشرفته

توابعی که فقط به انجام وظیفۀ سایر توابع کمک می کنند و در برنامۀ اصلی هیچ

کاربردی ندارند، بهتر است به صورت خصوصی اعلان شوند تا از دسترس سایرین در

امان بمانند.

9 سازندۀ کپی ‐7

می دانیم که به دو شیوه می توانیم متغیر جدیدی تعریف نماییم:

int x;

int x=k;

ایجاد می شود. در روش دوم هم int از نوع x در روش اول متغیری به نام

که k مقدار موجود در متغیر x همین کار انجام می گیرد با این تفاوت که پس از ایجاد

است. k یک کپی از x کپی می شود. اصطلاحا x از قبل وجود داشته درون

وقتی کلاس جدیدی تعریف می کنیم، با استفاده از تابع سازنده می توانیم اشیا را

به روش اول ایجاد کنیم:

Ratio x;

اعلان می شود. حال ببینیم چطور Ratio از نوع کلاس x در تعریف بالا، شی

می توانیم به شیوۀ دوم یک کپی از شیء موجود ایجاد کنیم. برای این کار از تابع عضوی

به نام سازندۀ کپی 1 استفاده می کنیم. این تابع نیز باید با نام کلاس هم نام باشد ولی

سازندۀ کپی بر خلاف تابع سازندۀ معمولی یک پارامتر به طریقۀ ارجاع ثابت دارد. نوع

این پارامتر باید هم نوع کلاس مذکور باشد. این پارامتر، همان شیئی است که می خواهیم

از روی آن کپی بسازیم. علت این که پارامتر مذکور به طریقۀ ارجاع ثابت ارسال

می شود این است که شیئی که قرار است کپی شود نباید توسط این تابع قابل تغییر

باشد. کدهای زیر هر دو تابع سازندۀ پیش فرض و سازندۀ کپی را نشان می دهد:

Ratio(); // default constructor

Ratio(const Ratio&); // copy constructor

اولی تابع سازندۀ پیش فرض است و دومی تابع سازندۀ کپی است. حالا می توانیم با

1 – Copy constructor

 

فصلم / شی گرایی 317

استفاده از این تابع، از روی یک شیء موجود یک کپی بسازیم:

Ratio y(x);

را x ایجاد می کند و تمام مشخصات شیء Ratio از نوع y کد بالا یک شی به نام

درون آن قرار می دهد. اگر در تعریف کلاس، سازندۀ کپی ذکر نشود (مثل همۀ

کلاس های قبلی) به طور خودکار یک سازندۀ کپی پیش فرض به کلاس افزوده خواهد

شد. با این وجود اگر خودتان تابع سازندۀ کپی را تعریف کنید، می توانید کنترل بیشتری

روی برنامه تان داشته باشید.

Ratio 9 افزودن یک سازندۀ کپی به کلاس ‐ * مثال 10

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n), den(d) { }

Ratio(const Ratio& r) : num(r.num), den(r.den) { }

void print() { cout << num << '/' << den; }

private:

int num, den;

};

int main()

{ Ratio x(100,360);

Ratio y(x);

cout << "x = ";

x.print();

cout << ", y = ";

y.print();

}

x = 100/360, y = 100/360

می بینید که در تعریف تابع سازندۀ کپی نیز می توان از فهرست مقداردهی پیش فرض

و num استفاده کرد. در مثال بالا، تابع سازندۀ کپی طوری تعریف شده که عنصرهای

به درون عنصرهای متناظر در شیء جدید کپی شوند. دستور r از پارامتر den

ساخته شده و سازندۀ کپی فرا خوانده y باعث می شود که شیء Ratio y(x);

کپی شوند. y درون x شود تا مقادیر موجود در شیء

 

318 برنامه سازی پیشرفته

سازندۀ کپی در سه وضعیت فرا خوانده می شود:

1 – وقتی که یک شی هنگام اعلان از روی شیء دیگر کپی شود

2 – وقتی که یک شی به وسیلۀ مقدار به یک تابع ارسال شود

3 – وقتی که یک شی به وسیلۀ مقدار از یک تابع بازگشت داده شود

برای درک این وضعیت ها به مثال زیر نگاه کنید.

9 دنبال کردن فراخوانی های سازندۀ کپی ‐ * مثال 11

class Ratio

{ public:

Ratio(int n=0, int d=1) : num(n), den(d) { }

Ratio(const Ratio& r) : num(r.num), den(r.den)

{ cout << "COPY CONSTRUCTOR CALLED\n"; }

private:

int num, den;

};

Ratio test(Ratio r) // calls the copy constructor, copying ? to r

{ Ratio q = r; // calls the copy constructor, copying r to q

return q; // calls the copy constructor, copying q to ?

}

int main()

{ Ratio x(22,7);

Ratio y(x); // calls the copy constructor, copying x to y

f(y);

}

COPY CONSTRUCTOR CALLED

COPY CONSTRUCTOR CALLED

COPY CONSTRUCTOR CALLED

COPY CONSTRUCTOR CALLED

بدنۀ سازندۀ کپی در برنامۀ بالا شامل یک پیغام است که هر وقت سازندۀ کپی

فراخوانی شود، با چاپ آن پیغام آگاه شویم که سازندۀ کپی فراخوانی شده. همان طور

که خروجی برنامه نشان می دهد، سازندۀ کپی چهار بار در برنامۀ بالا فراخوانی شده:

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 319

کپی می کند. y را درون x اعلان می شود، فراخوانی شده و y ‐ هنگامی که

y ارسال می شود، فراخوانی شده و test() به وسیلۀ مقدار به تابع y ‐ هنگامی که

کپی می کند. r را به درون

کپی می کند. q را به درون r اعلان می شود، فراخوانی شده و q ‐ هنگامی که

بازگشت داده می شود، فراخوانی test() به وسیلۀ مقدار از تابع q ‐ هنگامی که

می شود. حتی اگر چیزی را جایی کپی نکند.

ظاهری شبیه عمل جایگزینی دارد اما این کد در حقیقت Ratio q=r; دستور

است. Ratio q(r); سازندۀ کپی را فراخوانی می کند و درست شبیه دستور

اگر یک سازندۀ کپی در تعریف کلاستان نگنجانید، به طور خودکار یک سازندۀ

کپی برای آن منظور می شود که این سازنده به شکل پیش فرض تمام اطلاعات موجود

در شیء جاری را به درون شیء تازه ساخته شده کپی می کند. اغلب اوقات این همان

چیزی است که انتظار داریم. اما گاهی هم این کار کافی نیست و انتظارات ما را براورده

نمی کند. مثلا فرض کنید کلاسی دارید که یک عضو آن از نوع اشاره گر است. در حین

اجرای برنامه، این اشار هگر را به خان های از حافظه اشاره می دهید. حال اگر از این شی

یک کپی بسازید بدون این که از سازندۀ کپی مناسبی استفاده کنید، شیء جدید نیز به

همان خانه از حافظه اشاره می کند. یعنی فقط آن اشار هگر کپی می شود نه چیزی که به

آن اشاره می شود. در این گونه موارد لازم است خودتان تابع سازندۀ کپی را بنویسید و

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

9 نابود کننده ‐8

وقتی که یک شی ایجاد می شود، تابع سازنده به طور خودکار برای ساختن آن

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

خودکار فراخوانی می شود تا نابودکردن آن شی را مدیریت کند. این تابع عضو،

« منهدم کننده » یا « تخریب گر » نابودکننده 1 نامیده می شود (در برخی از کتا بها به آن

1 – Destructor

 

320 برنامه سازی پیشرفته

گفته اند). سازنده وظیفه دارد تا منابع لازم را برای شی تخصیص دهد و نابودکننده

وظیفه دارد آن منابع را آزاد کند.

هر کلاس فقط یک نابودکننده دارد. نام تابع نابودکننده باید هم نام کلاس مربوطه

باشد با این تفاوت که یک علامت نقیض ~ به آن پیشوند شده. مثل تابع سازنده و

سازندۀ کپی، اگر نابود کننده در تعریف کلاس ذکر نشود، به طور خودکار یک

نابودکنندۀ پیش فرض به کلاس افزوده خواهد شد.

Ratio 9 افزودن یک نابودکننده به کلاس ‐ * مثال 12

class Ratio

{ public:

Ratio() { cout << "OBJECT IS BORN.\n"; }

~Ratio() { cout << "OBJECT DIES.\n"; }

private:

int num, den;

};

int main()

{ { Ratio x; // beginning of scope for x

cout << "Now x is alive.\n";

} // end of scope for x

cout << "Now between blocks.\n";

{ Ratio y;

cout << "Now y is alive.\n";

}

}

OBJECT IS BORN.

Now x is alive.

OBJECT DIES.

Now between blocks.

OBJECT IS BORN.

Now y is alive.

OBJECT DIES.

در بدنۀ توابع سازنده و نابودکننده پیغامی درج شده تا هنگامی که یک شی از این

کلاس متولد شده یا می میرد، از تولد و مرگ آن آگاه شویم. خروجی نشان می دهد که

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 321

سازنده یا نابودکننده چه زمانی فراخوانی شده است. وقتی یک شی به پایان حوز هاش

برسد، نابودکننده فراخوانی می شود تا آن شی را نابود کند. یک شیء محلی وقتی به

برخورد main() پایان بلوک محلی برسد می میرد. یک شیء ثابت وقتی به پایان تابع

شود، می میرد. شیئی که درون یک تابع تعریف شده، در پایان آن تابع می میرد.

سعی کنید تابع نابودکننده را خودتان برای کلاس بنویسید. یک برنامه نویس

خوب، توابع سازنده و سازندۀ کپی و نابودکننده را خودش در تعریف کلاس هایش

می گنجاند و آن ها را به توابع پیش فرض سیستم واگذار نمی کند.

9 اشیای ثابت ‐9

اگر قرار است شیئی بسازید که در طول اجرای برنامه هیچ گاه تغییر نمی کند، بهتر

است منطقی رفتار کنید و آن شی را به شکل ثابت اعلان نمایید. اعلان های زیر چند

ثابت آشنا را نشان می دهند:

const char BLANK = ' ';

const int MAX_INT = 2147483647;

const double PI = 3.141592653589793;

void int(float a[], const int SIZE);

به صورت یک شیء ثابت اعلان کرد: const اشیا را نیز می توان با استفاده از عبارت

const Ratio PI(22,7);

اما در مورد اشیای ثابت یک محدودیت وجود دارد: کامپایلر اجازه نمی دهد که توابع

print() عضو را برای اشیای ثابت فراخوانی کنید. مثلا در مورد کد فوق گرچه تابع

نمی توانیم آن را فراخوانی PI است اما در مورد شیء ثابت Ratio عضوی از کلاس

کنیم:

PI.print(); // error: call not allowed

در اصل تنها توابع سازنده و نابودکننده برای اشیای ثابت قابل فراخوانی اند. ولی این

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

تعریف کنیم. برای این که یک تابع const اشیای ثابت کار کنند را باید به صورت

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

322 برنامه سازی پیشرفته

را بین فهرست پارامترها و تعریف بدنۀ const این چنین تعریف شود، کلمۀ کلیدی

را به شکل زیر تغییر Ratio در کلاس print() آن قرار می دهیم. مثلا تعریف تابع

می دهیم:

void print() const { cout << num << '/' << den << endl; }

اکنون می توانیم این تابع را برای اشیای ثابت نیز فراخوانی نماییم:

const Ratio PI(22,7);

PI.print(); // o.k. now

9 اشاره گر به اشیا ‐10

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

می تواند اشیای داده ای متنوع و متفاوتی داشته باشد، اشاره گر به اشیا بسیار سودمند و

مفید است. بهتر است قبل از مطالعۀ مثال های زیر، فصل هفتم را مرور کنید.

9 استفاده از اشار هگر به اشیا ‐ * مثال 13

class X

{ public:

int data;

};

main()

{ X* p = new X;

(*p).data = 22; // equivalent to: p->data = 22;

cout << "(*p).data = " << (*p).data << " = " << p->data << endl;

p->data = 44;

cout << " p->data = " << (*p).data << " = " << p->data << endl;

}

(*p).data = 22 = 22

p->data = 44 = 44

است و x یک شیء *p است. پس x اشاره گری به شیء p ، در این مثال

آن *p دادۀ عضو آن شی را دستیابی می کند. حتما باید هنگام استفاده از (*p).data

را درون پرانتز قرار دهید زیرا عملگر انتخاب عضو (.) تقدم بالاتری نسبت به عملگر

نوشته شود، کامپایلر *p.data مقداریابی (*) دارد. اگر پرانتزها قید نشوند و فقط

تفسیر خواهد کرد که این باعث خطا می شود. *(p.data) این خط را به صورت

 

فصلم / شی گرایی 323

هر دو به p->data و (*p).data این مثال نشان می دهد که دو عبارت

استفاده کنند p->data یک معنا هستند. بیشتر برنام هنویسان ترجیح می دهند از ترکیب

نزدیک تر است. مثال بعدی اهمیت « به آن اشاره می کند p چیزی که » زیرا به مفهوم

بیشتری دارد و کاربرد اشاره گر به اشیا را بهتر نشان می دهد.

Node 9 فهرست های پیوندی با استفاده از کلاس ‐ * مثال 14

به کلاسی که در زیر اعلان شده دقت کنید:

class Node

{ public:

Node(int d, Node* p=0) : data(d), next(p) { }

int data;

Node* next;

};

تعریف می کند که اشیای این کلاس دارای دو عضو Node عبارت بالا کلاسی به نام

است و دیگری یک اشاره گر از نوع همین int داده ای هستند که یکی متغیری از نوع

کلاس. شاید عجیب باشد که عضوی از کلاس به شیئی از نوع همان کلاس اشاره کند

اما این کار واقعا ممکن است و باعث می شود بتوانیم یک شی را با استفاده از همین

از s و r و q اشاره گر به شیء دیگر پیوند دهیم و یک زنجیره بسازیم. مثلا اگر اشیای

باشند، می توانیم پیوند این سه شی را به صورت زیر مجسم کنیم: Node نوع

به تابع سازنده نیز دقت کنید که چطور هر دو عضو داده ای شیء جدید را

مقداردهی می کند. اکنون این کلاس را در برنامۀ زیر به کار می گیریم:

int main()

{ int n;

Node* p;

Node* q=0;

while (cin >> n)

int data

q

Node* next

int data

r

int data

s

Node* next Node* next324 برنامه سازی پیشرفته

{ p = new Node(n, q);

q = p;

}

for ( ; p->next; p = p->next)

cout << p->data << " -> ";

cout << "*\n";

}

22 33 44 55 66 77 ^d

77 -> 66 -> 55 -> 44 -> 33 -> *

به یک q ساخته می شود که q و p به نام Node در این برنامه، ابتدا دو اشاره گر از نوع

پس از اولین ورودی، حافظۀ جدیدی برای while شیء خالی اشاره دارد. در حلقۀ

قرار p از اشاره گر data منظور می شود و عدد وارد شده در عضو داده ای p شیء

به p می شود. یعنی عضو اشاره گر q برابر با next می گیرد و همچنین عضو داده ای

به شیء q قرار می گیرد. حالا q در شیء p اشاره می کند. سپس آدرس شیء q حافظۀ

به یک شیء خالی. p اشاره دارد و p

منظور می شود و p پس از دومین ورودی، مجددا حافظۀ جدیدی برای

به q به حافظۀ موجود قبلی اشاره می کند و p انتساب های فوق تکرار می شود تا این که

اشاره می کند. شکل زیر روند اجرای برنامه را نشان می دهد. p شیء

0

q

next

0

q

next

data

p

next

0

q

next

data

next

data

p

next

الف - قبل از

شروع حلقه

ب - پس از اولین

تکرار حلقه

ج - پس از دومین

تکرار حلقه

 

 

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

 

فصلم / شی گرایی 325

ر ا فشار ندهد، حلقه ادامه (Ctrl+Z) تا زمانی که کاربر کاراکتر پایان فایل

یافته و هر دفعه یک عدد از ورودی گرفته شده و یک بند به زنجیرۀ موجود اضافه

وظیفۀ پیمایش فهرست پیوندی را دارد. به این صورت که تا for می شود. حلقۀ

وقتی

نباشد، حلقه ادامه می یابد و عضو داد های گره فعلی را چاپ NUL برابر با p->next

می کند و به این ترتیب کل فهرست پیمایش می شود. واضح است که برای پیمودن این

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

اشاره گر به اشیا بسیار سودمند و مفید است به حدی که بحث راجع به اشار هگر ها

ساختمان » و الگوریتم ها و مزایای آن به شاخۀ مستقلی در برنامه نویسی تبدیل شده و

نام گرفته است. به اختصار می گوییم که اشاره گر به اشیا برای ساختن « داده ها 1

فهرست های پیوندی و درخت های داده ای به کار می رود. این ها بیشتر برای

پردازش های سریع مثل جستجو در فهرست های طولانی (مانند فرهنگ لغات) یا

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

ساختمان داده ها مراجعه کنید.

9 اعضای داده ای ایستا ‐11

هر وقت که شیئی از روی یک کلاس ساخته می شود، آن شی مستقل از اشیای

دیگر، داده های عضو خاص خودش را دارد. گاهی لازم است که مقدار یک عضو

داده ای در همۀ اشیا یکسان باشد. اگر این عضو مفروض در همۀ اشیا تکرار شود، هم از

کارایی برنامه می کاهد و هم حافظه را تلف می کند. در چنین مواقعی بهتر است آن

عضو را به عنوان یک عضو ایستا 2 اعلان کنیم. عضو ایستا عضوی است که فقط یک

نمونه از آن ایجاد می شود و همه اشیا از همان نمونۀ مشترک استفاده می کنند. با استفاده

در شروع اعلان متغیر، می توانیم آن متغیر را به صورت ایستا static از کلمۀ کلیدی

اعلان نماییم. یک متغیر ایستا را فقط باید به طور مستقیم و مستقل از اشیا مقداردهی

نمود. کد زیر نحوۀ اعلان و مقداردهی یک عضو داده ای ایستا را بیان می کند:

class X

{ public:

1 – Data structure 2 – Static member

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

326 برنامه سازی پیشرفته

static int n; // declaration of n as a static data member

};

int X::n = 0; // definition of n

خط آخر نشان می دهد که متغیرهای ایستا را باید به طور مستقیم و مستقل از اشیا

مقداردهی کرد.

متغیرهای ایستا به طور پیش فرض با صفر مقداردهی اولیه می شوند. بنابراین

مقداردهی صریح به این گونه متغیرها ضروری نیست مگر این که بخواهید یک مقدار

اولیۀ غیر صفر داشته باشید.

9 یک عضو داده ای ایستا ‐ * مثال 15

اعلان می کند که این کلاس یک عضو داد های widget کد زیر، کلاسی به نام

که موجود هستند را نگه widget دارد. این عضو، تعداد اشیای count ایستا به نام

ساخته می شود، از طریق سازنده مقدار widget می دارد. هر وقت که یک شیء

نابود می شود، از widget یک واحد افزایش می یابد و هر زمان که یک شیء count

یک واحد کاهش می یابد: count طریق نابودکننده مقدار

class Widget

{ public:

Widget() { ++count; }

~Widget() { --count; }

static int count;

};

int Widget::count = 0;

main()

{ Widget w, x;

cout << "Now there are " << w.count << " widgets.\n";

{ Widget w, x, y, z;

cout << "Now there are " << w.count << " widgets.\n";

}

cout << "Now there are " << w.count << " widgets.\n";

Widget y;

cout << "Now there are " << w.count << " widgets.\n";

}

فصلم / شی گرایی 327

Now there are 2 widgets.

Now there are 6 widgets.

Now there are 2 widgets.

Now there are 3 widgets.

درون بلوک داخلی ایجاد شده است. widget توجه کنید که چگونه چهار شیء

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

ها از 6 به 2 تقلیل می یابد. widget کل

یک عضو داده ای ایستا مثل یک متغیر معمولی است: فقط یک نمونه از آن

موجود است بدون توجه به این که چه تعداد شی از آن کلاس موجود باشد. از آن جا

که عضو داده ای ایستا عضوی از کلاس است، می توانیم آن را به شکل یک عضو

خصوصی نیز اعلان کنیم.

9 یک عضو داده ای ایستا و خصوصی ‐ * مثال 16

class Widget

{ public:

Widget() { ++count; }

~Widget() { --count; }

int numWidgets() { return count; }

private:

static int count;

};

int Widget::count = 0;

main()

{ Widget w, x;

cout << "Now there are " << w.numWidgets() << " widgets.\n";

{ Widget w, x, y, z;

cout << "Now there are " << w.numWidgets() << " widgets.\n";

}

cout << "Now there are " << w.numWidgets() << " widgets.\n";

Widget y;

cout << "Now there are " << w.numWidgets() << " widgets.\n";

}

 

328 برنامه سازی پیشرفتهmohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

به count 9 کار می کند با این تفاوت که متغیر ایستای ‐ این برنامه مانند مثال 15

شکل یک عضو خصوصی اعلان شده

و به همین دلیل به تابع دستیابی

نیاز داریم تا numWidgets()

بتوانیم درون برنامۀ اصلی به متغیر

دسترسی داشته باشیم. count

را مانند مقابل تصور کنیم: w و y و x و اشیای Widget می توانیم کلاس

درون خود کلاس جای گرفته نه درون اشیا. count می بینید که متغیر ایستای

9 توابع عضو ایستا ‐12

count با دقت در مثال قبلی به دو ایراد بر می خوریم: اول این که گرچه متغیر

یک عضو ایستا است ولی برای خواندن آن حتما باید از یک شیء موجود استفاده کنیم.

برای خواندن آن استفاده کرد هایم. این باعث می شود که مجبور w در مثال قبلی از شیء

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

است فراخوانی شود. مثلا در مثال قبلی اگر در قسمتی از برنامه، دور از چشم ما، شیء

از آن به بعد مخاطره آمیز خواهد w.numWidgets() نابود شود، آنگاه فراخوانی w

بود. ایراد دوم این است که اگر هیچ شیئی موجود نباشد، نمی توانیم عضو ایستای

را دستیابی کنیم. برای رفع این دو ایراد کافی است تابع دستیابی کننده را نیز به count

شکل ایستا تعریف کنیم.

9 یک تابع عضو ایستا ‐ * مثال 17

کد زیر همان کد مثال قبلی است با این فرق که در این کد، تابع دستیابی کننده

نیز به شکل ایستا اعلان شده است:

class Widget

{ public:

Widget() { ++count; }

~Widget() { --count; }

static int num() { return count; }

Widget()

~Widget()

numWidgets()

count 3

Widget

x

y

w

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 329

private:

static int count;

};

int Widget::count = 0;

int main()

{ cout << "Now there are " << Widget::num() << " widgets.\n";

Widget w, x;

cout << "Now there are " << Widget::num() << " widgets.\n";

{ Widget w, x, y, z;

cout << "Now there are " << Widget::num() << " widgets.\n";

}

cout << "Now there are " << Widget::num() << " widgets.\n";

Widget y;

cout << "Now there are " << Widget::num() << " widgets.\n";

}

به صورت ایستا تعریف شود، از اشیای کلاس مستقل می شود و num() وقتی تابع

برای فراخوانی آن نیازی به یک شیء موجود نیست و می توان با کد

به شکل مستقیم آن را فراخوانی کرد. Widget::num()

تا این جا راجع به شی گرایی و نحو ۀ استفاده از آن در برنام هنویسی مطالبی آموختیم.

اکیدا توصیه می کنیم که قبل از مطالعۀ فصل بعدی، هم ۀ تمرین های پایان این فصل را

حل کنید تا با برنام هنویسی شی گرا مأنوس شوید. در فصل بعدی مطالبی را خواهیم دید

که شی گرایی را مفیدتر می کنند.

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

330 برنامه سازی پیشرفته

پرسش های گزینه ای

1 – کدام گزینه از مزایای شی گرایی نیست؟

الف – وراثت ب – چندریختی ج – بست هبندی د – نمونه سازی

2 – در اعلان یک کلاس، کدام گزینه صحیح است؟

استفاده می شود private الف – برای معرفی اعضای عمومی کلاس از عبارت

استفاده می شود public ب – برای معرفی اعضای خصوصی کلاس از عبارت

ج – توابع و متغیرها هر دو می توانند عضو یک کلاس باشند

استفاده می شود funct د – برای معرفی اعضای تابعی کلاس از عبارت

3 – کدام گزینه صحیح نیست؟

الف – به اعلان کلاس، رابط کلاس گفته می شود

ب – به بدنۀ کلاس، پیاده سازی کلاس گفته می شود

ج – به متغیری که از نوع یک کلاس باشد، شی گفته می شود

د – به تابعی که عضو یک کلاس باشد، تابع دستیابی گفته می شود

4 – از گزینه های زیر، کدام صحیح است؟

الف – هر کلاس فقط یک سازنده و فقط یک نابودکننده دارد

ب – هر کلاس فقط یک سازنده دارد و می تواند چند نابودکننده داشته باشد

ج – هر کلاس فقط یک نابودکننده دارد و می تواند چند سازنده داشته باشد

د – هر کلاس می تواند چند سازنده و چند نابودکننده داشته باشد

5 – تابع دستیابی چیست؟

الف – یک تابع عضو عمومی کلاس است که به یک دادۀ عضو عمومی دستیابی دارد

ب – یک تابع عضو خصوصی کلاس است که به یک دادۀ عضو خصوصی دستیابی دارد

ج – یک تابع عضو عمومی کلاس است که به یک دادۀ عضو خصوصی دستیابی دارد

د – یک تابع عضو خصوصی کلاس است که به یک داده عضو عمومی دستیابی دارد

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 331

داشته باشیم آنگاه کدام تابع زیر، سازندۀ کپی را برای vector 6 – اگر کلاسی به نام

این کلاس اعلان می کند؟

vector(const vector&) – ب vector() – الف

vector*(const vector) – د ~vector() ‐ ج

7 – سازندۀ کپی وقتی فراخوانی می شود که:

الف – یک شی به وسیلۀ مقدار به یک تابع فرستاده شود

ب – یک شی به وسیلۀ ارجاع به یک تابع فرستاده شود

ج – یک شی به وسیلۀ ارجاع ثابت به یک تابع فرستاده شود

د – یک شی به وسیلۀ ارجاع از یک تابع بازگشت داده شود

8 – اگر در تعریف یک کلاس، سازندۀ کپی ذکر نشود آنگاه:

الف – از اشیای آن کلاس نمی توان کپی ایجاد کرد

ب – اشیای آن کلاس را نمی توان به تابع فرستاد

ج – اشیای آن کلاس را نمی توان از تابع بازگشت داد

د – یک سازندۀ کپی پیش فرض به طور خودکار به کلاس افزوده می شود

به شکل محلی اعلان شده باشد، آنگاه : f() در تابع مفروض x 9 – اگر شیء

می میرد main() ایجاد می شود و در انتهای تابع x شیء main() الف – با شروع تابع

می میرد f() ایجاد می شود و در انتهای تابع x شیء main() ب – با شروع تابع

می میرد f() ایجاد می شود و در انتهای تابع x شیء f() ج – با شروع تابع

می میرد main() ایجاد می شود و در انتهای تابع x شیء f() د – با شروع تابع

10 – کدام گزینه در مورد کلاس ها صحیح است؟

الف – اشاره گرها می توانند عضو کلاس باشند ولی نمی توانند از نوع کلاس باشند

ب – اشاره گرها می توانند از نوع کلاس باشند ولی نمی توانند عضو کلاس باشند

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

د – اشاره گرها می توانند عضو کلاس باشند و می توانند از نوع کلاس باشند

 

 

332 برنامه سازی پیشرفته

اشیایی از x و 2 x بوده و 1 vector یک عضو ایستا برای کلاس k 11 – اگر متغیر

باشند، آنگاه: vector کلاس

فقط یک نمونه در سراسر برنامه موجود است. k الف – از

خاص خود را دارند k هر کدام عضو x و 2 x ب – 1

استفاده می کند k از همان x است و 2 k دارای عضو x ج – فقط 1

استفاده می کند k از همان x است و 1 k دارای عضو x د – فقط 2

12 – کدام گزینه در مورد اعضای ایستای کلاس، صحیح نیست؟

مشخص می شوند static الف – اعضای ایستا با کلمۀ کلیدی

ب – اعضای ایستا می توانند عضو عمومی کلاس باشند

ج – اعضای ایستا می توانند عضو خصوصی کلاس باشند

اعلان می شوند static: د – اعضای ایستا در بخش

در کدام تابع عضو کلاس استفاده می شود؟ « فهرست مقداردهی » ‐ 13

الف – تابع سودمند محلی ب – تابع نابودکننده

ج – تابع سازنده د – تابع دستیابی

media m2=m باشد، آنگاه با اجرای کد ; 1 media از کلاس m 14 – اگر شیء 1

کدام تابع عضو کلاس فراخوانی می شود؟

الف – تابع سازنده ب – تابع سازندۀ کپی

ج – تابع دستیابی د – تابع سودمند محلی

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

فصلم / شی گرایی 333

پرسش های تشریحی

1‐ تفاوت بین یک عضو عمومی و یک عضو خصوص ی از یک کلاس را توضی ح

دهید.

2‐ تفاوت بین رابط کلاس و پیاده سازی کلاس را توضی ح دهید.

3‐ تفاوت بین تابع عضو کلاس و تابع کاربردی را توضی ح دهید.

4‐ تفاوت بین سازنده و نابودکننده را توضی ح دهید.

5‐ تفاوت بین سازندۀ پیش فرض و سازنده های دیگر را توضی ح دهید.

6‐ تفاوت بین سازندۀ کپی و عملگر جایگزین ی را توضی ح دهید.

7‐ تفاوت بین تابع دستیابی و تابع سودمند محلی را توضیح دهید.

8‐ نام تابع سازنده چگونه باید باشد؟

9‐ نام تابع نابودکننده باید چگونه باشد؟

10 ‐ هر کلاس چه تعداد سازنده م یتواند داشته باشد؟

11 ‐ هر کلاس چه تعداد نابودکننده می تواند داشته باشد؟

12 ‐ چگونه و چرا از عملگر جداسازی حوزه :: در تعریف کلاس ها استفاده

می شود؟

13 ‐ کدام تابع عضو به طور خودکار توسط کامپایلر ایجاد م یشود اگر برنام هنویس آن

را صریحا در تعریف کلاس نگنجانیده باشد؟

14 ‐ در کد زیر چند دفعه سازندۀ کپی فراخوانی م یشود؟

Widget f(Widget u)

{ Widget v(u);

Widget w = v;

return w;

}

main()

{ Widget x;

Widget y = f(f(x));

}

 

334 برنامه سازی پیشرفته

وجود پرانتزها ضروری است؟ (*P).data 15 ‐ چرا در عبارت

تمرین های برنامه نویسی

پیاده سازی کنید. یک (x, y, z) را برای نقاط سه بعدی Point 1‐ کلاس

تا نقطۀ مورد نظر را منفی negate() سازندۀ پیش فرض، یک سازندۀ کپی، یک تابع

0) و یک تابع , 0, برای برگرداندن فاصله از مبداء ( 0 norm() کند، یک تابع

به این کلاس اضافه کنید. print()

پیاده سازی کنید. یک سازندۀ int را برای پشته هایی از نوع stack 2‐ کلاس

pop() و push() پیش فرض، یک نابودکننده و توابع اجرای عملیات معمول پشته

را به این کلاس اضافه کنید. از آرایه ها برای این isFull() و isEmpty() و

پیاده سازی استفاده کنید.

را پیاد هسازی کنید. هر شی از این کلاس، یک زمان ویژه از روز را Time 3‐ کلاس

نشان می دهد که ساعت، دقیقه و ثانیه را به شکل یک عدد صحیح نگهداری می کند.

برای جلو advance(int h,int m,int s) یک سازنده، توابع دستیابی، تاب ع

برای reset(int h,int m,int s) بردن زمان فعلی یک شی ء موجود، تابع

به این کلاس اضافه کنید. print() نو کردن زمان فعلی یک شی ء موجود و یک تابع

را برای تولید کردن اعداد شبه تصادفی پیاده سازی کنید. Random 4‐ کلاس

را پیاده سازی کنید. هر شی از این کلاس، نمایان گر یک انسان person 5‐ کلاس

است. اعضای داد های این کلاس باید شامل نام شخص، سال تولد و سال وفات باشد.

به این print() یک تابع سازندۀ پیش فرض، نابودکننده، توابع دستیابی و یک تابع

کلاس اضافه کنید.

2 پیاده سازی کنید: × را برای آرایه های 2 Matrix 6‐ کلاس

⎥⎦

⎢⎣

c d

a b

که معکوس آرایه را inverse() یک سازندۀ پیش فرض، یک سازندۀ کپی ، یک تابع

که دترمینان آرایه را برمی گرداند، یک تابع بولی det() برمی گرداند، یک تابع

 

فصلم / شی گرایی 335

که بسته به این که دترمینان صفر باشد یا نه مقدار یک یا صفر را isSingular()

به این کلاس اضافه کنید. print() برمی گرداند و یک تابع

پیاده سازی کنید. یک سازندۀ (x, y) برای نقاط دو بعدی point 7‐ یک کلاس

برای تبدیل نقطۀ مورد نظر به negate() پیش فرض، یک سازندۀ کپی، یک تابع

برای برگرداندن فاصلۀ نقطه از مبداء ( 0,0 ) و یک تابع norm() منفی، یک تابع

به این کلاس اضافه کنید. print()

را پیاده سازی کنید. هر شی در این کلاس یک دایره را نشان Circle 8‐ کلاس

نگهداری float از مرکز را به صورت y و x می دهد که شعاع آن و مختصات

و یک تابع area() می کند. یک سازندۀ پیش فرض، توابع دستیابی، یک تابع

که محیط دایرۀ مذکور را برمی گرداند، به این کلاس اضافه circumference()

کنید.

به آن، تغییر دهید. تابع count() در مسألۀ 2 را با افزودن تابع Stack 9‐ کلاس

مذکور تعداد اقلام درون پشته را برمی گرداند.

تغییر دهید. تابع print() در مسألۀ قبل را با افزودن تابع Stack 10 ‐ کلاس

مذکور محتویات پشته را چاپ می کند.

،int در مسألۀ قبل را طوری تغییر دهید که به جای مقادیر نوع Stack 11 ‐ کلاس

را نگهداری کند. float مقدارهای

area() در مسألۀ 8 را طوری تغییر دهید که شامل تابع Circle 12 ‐ کلاس

باشد. این تابع مساحت دایرۀ مذکور را برمی گرداند.

3 را × در مسألۀ 6 را طوری تغییر دهید که آرایه های 3 Matrix 13 ‐ کلاس

نگهداری کند. توابع عضو را طوری تغییر دهید که با این آرایه ها سازگار باشند.

mohsen_mahyar@yahoo.com

mo-mah.persianblog.ir

 

   + MOHSEN GHASEMI - ۱٢:٤۳ ‎ق.ظ ; ۱۳۸٩/٥/٢٤

فصل هشتم استاندارد رشته های کاراکتری و فایل ها در » در++ C

<!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

mohsen_mahyar@yahoo.com

فصل هفتم

      C++ در « اشاره گرها 1 و ارجاع ها 2 »

7 مقدمه ‐1

حافظۀ رایانه را می توان به صورت یک آرایۀ بزرگ در

در RAM نظر گرفت. برای مثال رایانه ای با 256 مگابایت

حقیقت حاوی آرایه ای به اندازۀ 268،435،456

228 ) خانه است که اندازۀ هر خانه یک بایت است. این =)

خانه ها دارای ایندکس صفر تا 268،435،455 هستند.

به ایندکس هر بایت، آدرس حافظۀ آن می گویند. آدرس های

حافظه را با اعداد شانزده دهی نشان می دهند. پس رایانۀ مذکور

0 می باشد. هر وقت که x0fffffff 0 تا x دارای محدوده آدرس 00000000

نوع » : متغیری را اعلان می کنیم، سه ویژگی اساسی به آن متغیر نسبت داده می شود

و n و نام int نوع int n; آن. مثلا اعلان « آدرس حافظه » و « نام متغیر » و « متغیر

در آن قرار می گیرد را به یکدیگر مرتبط n آدرس چند خانه از حافظه که مقدار

را n 0 است. بنابراین می توانیم x0050cdc می سازد. فرض کنید آدرس این متغیر 0

0x00000000

0x00000001

0x00000002

0x00000003

0x00000004

0x00000005

0x00000006

0x00000007

0x0064fdc5

0x0064fdc6

0x0064fdc7

0x0064fdc8

0x0ffffffe

 

0x0fffffff

1 – Pointers 2 – References

فصل هفتم / اشاره گرها و ارجا ع ها 215

مانند شکل زیر مجسم کنیم:

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

در بالای جعبه است و آدرس متغیر در سمت چپ جعبه و ،n

در زیر جعبه نشان داده شده. در بیشتر ،int ، نوع متغیر

چهار بایت از حافظه را اشغال می نماید. int رایانه ها نوع

بنابراین همان طور که در شکل مقابل نشان داده شده است،

یک بلوک چهاربایتی از حافظه را اشغال می کند که n متغیر

0 است. x0050cdc 0 تا 3 x0050cdc شامل بایت های 0

توجه کنید که آدرس شی، آدرس اولین بایت از بلوکی است که شی در آن جا ذخیره

مقداردهی اولیه شود، آنگاه بلوک حافظه int n= شده. اگر متغیر فوق به شکل ; 32

به شکل زیر خواهد بود. مقدار

32 در چهار بایتی که برای آن

متغیر منظور شده ذخیره می شود.

در این فصل به بررسی و نحوۀ استفاده از آدر سها خواهیم پرداخت.

7 عملگر ارجاع ‐1

& برای بدست آوردن آدرس یک متغیر می توان از عملگر ارجاع 1 C++ در

را n آدرس متغیر &n نیز می گویند. عبارت « علمگر آدرس » استفاده نمود. به این عملگر

به دست می دهد.

7 چاپ آدرس یک متغیر ‐ * مثال 1

int main()

{ int n=44;

cout << " n = " << n << endl; // prints the value of n

cout << "&n = " << &n << endl; // prints the address of n

}

n = 44

&n = 0x00c9fdc3

0x0050cdc0

n

int

0x0050cdb8

0x0050cdb9

0x0050cdc0

0x0050cdc1

0x0050cdc2

0x0050cdc3

0x0050cdc4

0x0050cdc5

0x0050cdb8