SlideShare a Scribd company logo
1 of 14
‫کتاب‬ ‫معرفی‬
‫های‬ ‫مکانیزم‬Abstraction
‫های‬ ‫کالس‬Concrete
‫منبع‬:‫کتاب‬The C++ programming language‫نوشته‬
‫آقای‬Bjarne Stroustrup
‫ها‬ ‫کالس‬
Concrete Class
Abstract Class
Classes in hierarchies
‫مشابه‬ ‫عملکرد‬Built-in type‫ها‬
‫یا‬ ‫نمایش‬Representation‫از‬ ‫بخشی‬ ‫آنها‬Definition
‫آنهاست‬
‫در‬ ‫داری‬ ‫نگه‬stack‫صورت‬ ‫به‬ ‫حافظه‬ ‫تخصیص‬ ‫و‬static‫است‬.
‫گیرد‬ ‫می‬ ‫صورت‬ ‫مستقیم‬ ‫صورت‬ ‫به‬ ‫اجاع‬ ‫و‬ ‫دسترسی‬.
‫با‬ ‫و‬ ‫کامل‬ ‫صورت‬ ‫به‬ ‫اولیه‬ ‫دهی‬ ‫مقدار‬constructor‫گیرد‬ ‫می‬ ‫صورت‬.
‫قابلیت‬copy‫دارند‬ ‫کردن‬.
01. class complex {
02. double re, im; // Representation: two doubles
03. public:
04. // Construct complex from two scalars
05. complex(double r, double i) : re(r), im(i) {}
06. complex(double r) : re(r), im(0) {}// Construct complrex from one scalar
07. complex() : re(0), im(0) {} // Default complex: {0,0}
08.
09. double real() const { return re; }
10. void real(double d) { re = d; }
11. double image() const { return im; }
12. void image(double d) { im = d; }
13.
14. // Add to re and im and return the result
15. complex& operator+=(complex& z) { re+=z.re; im+=z.im; return *this; }
16. complex& operator-=(complex& z) { re-=z.re; im-=z.im; return *this; }
17. complex& operator*=(complex& z); // Defined out-of-class somewhere
18. complex& operator/=(complex& z); // Defined out-of-class somewhere
19. };
01. complex operator+(complex a, complex b) { return a += b; }
02. complex operator-(complex a, complex b) { return a -= b; }
03. // Unary minus
04. complex operator-(complex a) { return complex(-a.real(), -a.image()); }
05. complex operator*(complex a, complex b) { return a *= b; }
06. complex operator/(complex a, complex b) { return a /= b; }
07.
08. bool operator==(complex a, complex b) // Equal
09. {
10. return a.real() == b.real() && a.image() == b.image();
11. }
12.
13. bool operator!=(complex a, complex b) // Not equal
14. {
15. return !(a == b);
16. }
17.
18. complex sqrt(complex);
01. void f(complex z)
02. {
03. // Construct {2.3, 0.0} from 2.3
04. complex a(2.3);
05. complex b(1/a);
06. complex c(a + z * complex(1, 2.3));
07.
08. // ...
09.
10. if (c != b)
11. c = -(b / a) + 2 * b;
12. }
01. class Vector {
02. private:
03. double* elem; // Elem points to an array of sz doubles
04. int sz;
05. public:
06. // Constructor: acquire resources
07. Vector(int s) : elem(new double[s]), sz(s)
08. {
09. // Initialize elements
10. for (int i=0; i!=s; ++i) elem[i] = 0;
11. }
12.
13. // Destructor: release resources
14. ~Vector() { delete[] elem; }
15.
16. double& operator[](int i);
17. int size() const;
18. }
01. void fct(int n)
02. {
03. Vector v(n);
04.
05. // ... use v ...
06.
07. {
08. Vector v2(2 * n);
09.
10. // ... use v and v2 ...
11.
12. } // v2 is destroyed here
13.
14. // ... use v ...
15.
16. } // v is destroyed here
Initializer list
push_back
01. class Vector {
02. public:
03. Vector(std::initializer_lsit<double> lst);
04. void push_back(double d);
05. }
06.
07. Vector::Vector(std::initializer_list<double> lst)
08. : elem(new double[lst.size()], sz(lst.size)
09. {
10. copy(lst.begin(), lst.end(), elem);
11. }
12.
13. Vector v1 = {1,2,3,4,5};
14. Vector v2 = {1.23, 3.45, 6.7, 8};
01. Vector read(istream& is)
02. {
03. // Read floating-point values into d
04. Vector v;
05. for (double d; is >> d;)
06. v.push_back(d); // Add d to v
07. return v;
08. }
7. abstraction mechanisms, containers

More Related Content

More from Vahid Heidari

9. class hierarchies
9. class hierarchies9. class hierarchies
9. class hierarchiesVahid Heidari
 
6. separation, namespace, error
6. separation, namespace, error6. separation, namespace, error
6. separation, namespace, errorVahid Heidari
 
5. struct, class, enum
5. struct, class, enum5. struct, class, enum
5. struct, class, enumVahid Heidari
 
2. types, vars, arith, consts
2. types, vars, arith, consts2. types, vars, arith, consts
2. types, vars, arith, constsVahid Heidari
 
1. preface, hello world
1. preface, hello world1. preface, hello world
1. preface, hello worldVahid Heidari
 

More from Vahid Heidari (10)

11. template
11. template11. template
11. template
 
10. copy and move
10. copy and move10. copy and move
10. copy and move
 
9. class hierarchies
9. class hierarchies9. class hierarchies
9. class hierarchies
 
8. abstract types
8. abstract types8. abstract types
8. abstract types
 
6. separation, namespace, error
6. separation, namespace, error6. separation, namespace, error
6. separation, namespace, error
 
5. struct, class, enum
5. struct, class, enum5. struct, class, enum
5. struct, class, enum
 
4. pointers, arrays
4. pointers, arrays4. pointers, arrays
4. pointers, arrays
 
3. tests, loops
3. tests, loops3. tests, loops
3. tests, loops
 
2. types, vars, arith, consts
2. types, vars, arith, consts2. types, vars, arith, consts
2. types, vars, arith, consts
 
1. preface, hello world
1. preface, hello world1. preface, hello world
1. preface, hello world
 

7. abstraction mechanisms, containers

  • 1.
  • 3. ‫منبع‬:‫کتاب‬The C++ programming language‫نوشته‬ ‫آقای‬Bjarne Stroustrup
  • 5. ‫مشابه‬ ‫عملکرد‬Built-in type‫ها‬ ‫یا‬ ‫نمایش‬Representation‫از‬ ‫بخشی‬ ‫آنها‬Definition ‫آنهاست‬ ‫در‬ ‫داری‬ ‫نگه‬stack‫صورت‬ ‫به‬ ‫حافظه‬ ‫تخصیص‬ ‫و‬static‫است‬. ‫گیرد‬ ‫می‬ ‫صورت‬ ‫مستقیم‬ ‫صورت‬ ‫به‬ ‫اجاع‬ ‫و‬ ‫دسترسی‬. ‫با‬ ‫و‬ ‫کامل‬ ‫صورت‬ ‫به‬ ‫اولیه‬ ‫دهی‬ ‫مقدار‬constructor‫گیرد‬ ‫می‬ ‫صورت‬. ‫قابلیت‬copy‫دارند‬ ‫کردن‬.
  • 6. 01. class complex { 02. double re, im; // Representation: two doubles 03. public: 04. // Construct complex from two scalars 05. complex(double r, double i) : re(r), im(i) {} 06. complex(double r) : re(r), im(0) {}// Construct complrex from one scalar 07. complex() : re(0), im(0) {} // Default complex: {0,0} 08. 09. double real() const { return re; } 10. void real(double d) { re = d; } 11. double image() const { return im; } 12. void image(double d) { im = d; } 13. 14. // Add to re and im and return the result 15. complex& operator+=(complex& z) { re+=z.re; im+=z.im; return *this; } 16. complex& operator-=(complex& z) { re-=z.re; im-=z.im; return *this; } 17. complex& operator*=(complex& z); // Defined out-of-class somewhere 18. complex& operator/=(complex& z); // Defined out-of-class somewhere 19. };
  • 7. 01. complex operator+(complex a, complex b) { return a += b; } 02. complex operator-(complex a, complex b) { return a -= b; } 03. // Unary minus 04. complex operator-(complex a) { return complex(-a.real(), -a.image()); } 05. complex operator*(complex a, complex b) { return a *= b; } 06. complex operator/(complex a, complex b) { return a /= b; } 07. 08. bool operator==(complex a, complex b) // Equal 09. { 10. return a.real() == b.real() && a.image() == b.image(); 11. } 12. 13. bool operator!=(complex a, complex b) // Not equal 14. { 15. return !(a == b); 16. } 17. 18. complex sqrt(complex);
  • 8. 01. void f(complex z) 02. { 03. // Construct {2.3, 0.0} from 2.3 04. complex a(2.3); 05. complex b(1/a); 06. complex c(a + z * complex(1, 2.3)); 07. 08. // ... 09. 10. if (c != b) 11. c = -(b / a) + 2 * b; 12. }
  • 9. 01. class Vector { 02. private: 03. double* elem; // Elem points to an array of sz doubles 04. int sz; 05. public: 06. // Constructor: acquire resources 07. Vector(int s) : elem(new double[s]), sz(s) 08. { 09. // Initialize elements 10. for (int i=0; i!=s; ++i) elem[i] = 0; 11. } 12. 13. // Destructor: release resources 14. ~Vector() { delete[] elem; } 15. 16. double& operator[](int i); 17. int size() const; 18. }
  • 10. 01. void fct(int n) 02. { 03. Vector v(n); 04. 05. // ... use v ... 06. 07. { 08. Vector v2(2 * n); 09. 10. // ... use v and v2 ... 11. 12. } // v2 is destroyed here 13. 14. // ... use v ... 15. 16. } // v is destroyed here
  • 12. 01. class Vector { 02. public: 03. Vector(std::initializer_lsit<double> lst); 04. void push_back(double d); 05. } 06. 07. Vector::Vector(std::initializer_list<double> lst) 08. : elem(new double[lst.size()], sz(lst.size) 09. { 10. copy(lst.begin(), lst.end(), elem); 11. } 12. 13. Vector v1 = {1,2,3,4,5}; 14. Vector v2 = {1.23, 3.45, 6.7, 8};
  • 13. 01. Vector read(istream& is) 02. { 03. // Read floating-point values into d 04. Vector v; 05. for (double d; is >> d;) 06. v.push_back(d); // Add d to v 07. return v; 08. }

Editor's Notes

  1. مطالبی که قصد دارم در این ویدیو ارائه بدم ابتدا دوباره منبع رو معرفی می کنم و یه مقدمه ای رو می گم. بعد مکانیزم های Abstraction و مباحث اون رو در C++ بحث می کنم. و مفهوم Concrete کلاس رو با چند تا مثال بررسی می کنیم.
  2. منبع کتاب the c++ programming language هست edition چهارم نوشته ی آقای استرو استراپ. نویسنده ی این کتاب مخترع، سازنده یا inventorی زبان C++ هستش. در 6 ویدیوی قبلی ما فصل دوم از Part I کتاب رو با هم مرور کردیم و در مورد Language Core Feature ها صحبت کردیم و یک معرفی در مورد basicی زبان داشتیم و الان وارد فصل سوم کتاب شدیم. از این ویدیو به بعد پیوستگی مباحث خیلی بیشتر میشه. با این مقدمه میریم سراغ فصل سوم.
  3. در فصل سوم بدون ورود به جزئیات خیلی زیاد مفاهیم Abstraction و Resource Management رو بررسی می کنیم. در واقع بدون اینکه مستقیما اشاره بشه داریم در مورد کاربردهای User-defined typeها که در ویدیوی شماره 5 بحث کردیم صحبت می کنیم. این مکانیزم ها امکانات زبان برای ورود به برنامه نوسی شی گرا یا Object Oriented و همین طور Generic Programming هستند. اما کلاس ها یکی از ویژگیهای محوری زبان محسوب می شند و با استفاده از اونا هر ایده و مفهوم و یا موجودیت ها رو به صورت کدهای برنامه تبدیل می کنیم و سعی می کنیم به شکل کلاس بنویسیم. کلاس ها در واقع اجازه میدن که فراتر از Fundamental-typeها و عملگرهای از پیش تعریف شده ی اونا عمل کنیم و به ما کمک می کنه که بهتر اون Fundamental-typeها استفاده کنیم. ما در زبان C++ سه نوع کلاس داریم. کلاسهای Concrete. کلاسهای Abstract و کلاسهای سلسله مراتبی. تمام انواع دیگه ی کلاس ها یا مستقیما از این انواع هستند و یا اینکه ترکیبی از اینها هستند. در این ویدیو کلاسهای Concrete رو بحث می کنیم و بقیه رو در آینده بحث خواهیم کرد.
  4. ایده ی اصلی concrete کلاس ها اینه که مشابه Built-in typeها رفتار کنند یعنی مشابه int و char و غیره؛ ولی semantic و عملگرهای مخصوص خودشون رو داشته باشند. به عنوان مثال vector که یه user-defined type هست مشابه آرایه که built-in type هست کار میکنه ولی در vector کنترل بیشتری داریم و امکانات بیشتری نسبت به آرایه به ما میده. یکی از خصوصیات concrete classها اینه که نمایش یا representation اون ها بخشی از definition اونهاست. به عنوان مثالrepresentation اون vector که قبلا تعریف کردیم شامل یک یا چند pointer بود که به dataهایی که یه جای دیگه ذخیره شده بودند اشاره می کرد. این اشارگرها داخل کلاس تعریف شدند و اصطلاحا داخل کلاس Present هستند یا به عبارتی حضور دارند. به عبارت دیگه به ما اجازه می ده که concrete کلاسها رو در stack نگه داری کنیم و به صورت static حافظه در اختیار اونها قرار بدیم. این به ما اجازه می ده که به صورت بهینه بهشون دسترسی داشته باشیم. این یکی بودن representation و definition باعث می شه که هر تغییر در کلاس باعث بشه که شما مجبور بشید کل پروژه رو دوباره از اول کامپایل کنید تا به تمام کسانی که از اون کلاس استفاده می کنند اطلاع بدید که تغییراتی در کلاس بوجود اومده. همینطور مکانیزم هایی مثل constructor به ما امکان میده که اونو Initialize کنیم و امکان کپی کردن member wise هم به ما میده.
  5. در این اسلاید یک مثال ساده شده از کلاس complex که یکی از کلاسهای کتابخونه ی استاندارد هست رو بررسی می کنیم. این کلاس پیاده سازی اعداد مختلطه که عملیاتهای ریاضی مربوط به اون رو انجام میده و در واقع یک arithmetic type یا یک type ریاضیاتی هست. هدف اینه که خیلی ساده باشه و توابع ساده Inline شده باشن، هر وقت که شما در داخل decleration یک کلاس definition یا بدنه ی تابع رو هم بنویسید به اصطلاح به اون تابع می گیم که Inline شده؛ مثل اپراتور های += و تابع image(). از مزایای توابع inline اینه که function call برای اونا صورت نمی گیره. کانستراکتوری که هیچ پارامتر ورودی نداره رو بهش می گیم Default Constructor. با تعریف default constructor شما می تونید تمامی Memberهای کلاس رو مقدار دهی کنید و مطمئن بشید که همشون مقدار اولیه گرفتند. کلمه ی const سمت راست در توابع real و image میگه که با call شدن این توابع قسمت موهومی و حقیقی دستکاری نمی شن و فراخوانی تابع باعث تغییر memberهای اون نمیشه و state کلاس عوض نخواهد شد.
  6. خیلی از اپراتورها هستند که اصلا نیازی نداریم به representation کلاس دسترسی داشته باشیم پس اونا رو خارج از کلاس تعریف می کنیم. و در داخل بدنه ی اونا از اپراتورهایی که برای کلاس تعریف کردیم استفاده می کنیم. یک نکته هم در این اپراتور ها وجود داره اینه که پارامتر ها به صورت کپی به تابع pass میشن و عملیات روی کپی های اونا انجام میشه و حاصل عملیات هم به وسیله ی اونا برگردونده میشه. تعریف اپراتورهای == و != هم خیلی ساده و سر راست هست. فقط قسمتهای موهومی باید با هم و قسمت های حقیقی هم باید با هم برابر باشند. خط آخر هم Decleration تابع مجذور مخلط رو می بیند که Definition اون اینجا انجام نشده.
  7. و نحوه ی استفاده از کلاس های concrete به صوتی خیلی ساده و دقیقا مشابه fundamental-typeهاست. کامپایلر هرجا که complex در عملیاتها حضور داشته باشه توابع و اپراتورهای مناسب رو call میکنه. برای مثال بجای c!=b اپراتور مناسب رو call می کنه و بجای پارامترها ورودی اول، متغییر c و بجای پارامتر دوم متغییر b رو قرار میده. نکته ای که در استفاد از اپراتورها و تعریف اپراتورهای جدید وجود داره اینه که شما باید از قواعد زبان پیروی کنید. مثلا نمی تونید یک اپراتور تک عملوندی برای تقسیم تعریف کنید. تقسیم حتما یه مقسوم داره و یه مقسوم علیه و این قابل تغییر نیست. یک توصیه هم وجود داره که میگه برای typeهای جدیدی که تعریف می کنید معنای اپراتورها رو تغییر ندید یعنی مثلا برای اپراتور جمع عملیات تفریق رو پیاده سازی نکنید. هر اپراتور رو با همون معنایی که داره پیاده سازی کنید.
  8. Container یک Object هست که یکسری المان رو در خودش نگه می داره. پس ما Vector رو یک نوع از Container می دونیم بخاطر اینکه یک سری double رو در خودش نگه می داره. Vector یک Container ساده هست که یکسری سرویسهای مفید رو به ما ارائه می ده و یکسری range checking هایی برای ما انجام میده که دسترسی غیر مجاز نداشته باشیم. اما Vectorی که ما تا اینجا تعریف کردیم یه مشکلی داشت. ما با استفاده از new حافظه ای رو در ختیار می گیریم اما زمانی که کارمون تموم میشه حافظه ای که allocate کردیم رو آزاد نمی کنیم و حافظه de-allocate نمیشه. C++ یکسری قوانین برای ایجاد و ازبین بردن Objectها داره ولی یه زمانهایی ما نیاز داریم که زمانی که یک Object داره نابود میشه کنترل بیشتری داشته باشیم و مطمئن بشیم که حافظه آزاد میشه و اصطلاحا memory leak نداریم. مکانیزمی که زبان به ما میده استفاده از destructor هست. Destructor همنام با اسم کلاس هست و با علامت ~ مشخص میشه و معناش اینه که بر عکس Constructor عمل میکنه. Constructor برای ایجاد یک Object هست و در اون ما حافظه ی مورد نیاز رو با استفاده از new، Allocate می کنیم . ولی Destructor برای زمان نابود شدن Object هست و با استفاده از delete حافظه ای که در اختیار گرفتیم de-allocate می کنیم. نحوه ی call شدن Destructor توسط کامپایلر انجام میشه و برنامه نویش لازم نیست که این مستقیما Destructor رو Call کنه.
  9. در نحوه ی استفاده هم همون قوانین که برای نامگذاری و اسکوپ و life time و غیره در مورد fundamental typeها مثل int و char بکار برده میشن برای Vector هم بکار برده میشه. بکار بردن و نوشتن Constructor و destructor پایه ی مدیریت منابع در C++ هست. در Constructor حافظه ی مورد نیاز رو Allocate میکنیم و به memberها مقدار اولیه میدیم و زمانی که از اسکوپ خارج میشیم به صورت خودکار destructor اجرا میشه و در اون حافظه رو de-allocate می کنیم. به این تکنیک که زمانی که یک شئ رو ایجاد می کنید Constructor اون مقادیر داخل اون کلاس رو مقدار دهی اولیه می کنه در اصطلاح می گیم RAII که مخفف Resource Acquisition Is Initialization هست. تکنیک RAII باعث میشه که شما کمتر از new و delete استفاده کنید و مجبور نباشید که همشه حواستون باشه که هر چی newکردید رو delete کنید. داخل Constructor و Destructor این کارها رو انجام میدید و خود کاپایلر در زمان مناسب اونا رو call میکنه و حافظه آزاد میشه و جلوی leakشدن حافظه گرفته می شه.
  10. کار Containerاینه که یک سری المان رو داخل خودش نگه داره. برای اینکار ما نیاز به یک استانداردی داریم تا بتونیم مقادر رو بهش اضافه کنیم. تا اینجا ما Vectorی رو میساختیم و مقادیر رو بهش assign می کردیم. ولی راه بهتری هم وجود داره و اون استفاده از initializer list و push_back هست.
  11. با استفاده از Initialiser-List constructor میتونیم در زمان ساخته شدن Container یک list از المانهایی که می خوایم رو به عنوان مقدار اولیه به Container بدیم. در پیاده سازی initializer-list constructor کاری که می کنیم اینه که به اندازه ی عناصر داخل لیست فضا allocate میکنیم و بعد تمام عناصر لیست رو داخل اون فضا copy می کنیم. Std::initializer_list یکی از typeهای شناخته شده برای کامپایلر هست و وقتی که از آکولاد باز و بسته برای مقدار اولیه دادن به یک Container استفاده می کنید کامپایلر به صورت اوتوماتیک یک شئ از نوع InitializerList میسازه و کانستراکتور مناسب رو با اون صدا میزنه.
  12. تابع push_back یک المان جدید رو به انتهای Container اضافه می کنه. در این مثال می بینید که از push_back برای خوندن تعداد دلخواهی ورودی از کاربر و اضافه کردن به انتهای vector استفاده شده. حلقه زمانی خاتمه پیدام میکنه که به انتهای ورودی برسیم و یا یک خطایی در پارس کردن ورودی رخ بده مثلا بجای اینکه یه عدد اعشاری وارد کنیم یه رشته وارد کنیم. تا زمانی که حلقه تکرار میشه یک عدد خونده میشه و با Push_back به vector اضافه میشه. اینجا از حلقه for بجای while استفاده شده تا بتونیم اسکوپ متغییر d رو کنترل کنیم و فقط داخل حلقه for بهش دسترسی داشته باشیم.
  13. در این ویدیو وارد فصل سوم کتاب شدیم که در مورد مکانیزهای Abstraction هست. یه معرفی در مورد مکانیزم های Abstraction کردیم و Concrete کلاسها رو بررسی کردیم و به عنوان مثال پیاده سازی Containerهای ساده مثل Vector رو بررسی کردیم.