بخش ۷ - مفاهیم پایهی شیءگرایی
در این بخش، تعریف یک کلاس ساده برای نگهداری تاریخ مورد بررسی قرار میگیرد. این کلاس طی مثالهای متوالی کاملتر میشود.
فهرست مثالها
پیادهسازی ابتدایی تاریخ در قالب یک کلاس
#include <iostream> #include <cstdlib> using namespace std; class Date { public: void set_date(int d, int m, int y); void print_date(); private: int day; int month; int year; }; void Date::set_date(int d, int m, int y) { if (y < 0 || m < 1 || m > 12 || d < 1 || (m < 7 && d > 31) || (m > 6 && m < 12 && d > 30) || (m == 12 && d > 29)) abort(); day = d; month = m; year = y; } void Date::print_date() { cout << day << '/' << month << '/' << year << endl; } int main() { Date bd; bd.set_date(31, 6, 1352); bd.print_date(); // bd.day = 14; }
اضافه شدن سازنده (constructor) به کلاس تاریخ
class Date { public: Date(int d, int m, int y); }; Date::Date(int d, int m, int y) { set_date(d, m, y); } int main() { // Date bd; Date bd(31, 6, 1352); bd.print_date(); cout << '\n'; }
دسترسی به اعضای خصوصی تاریخ از طریق getter ها
class Date { public: int get_day() { return day; } int get_month() { return month; } int get_year() { return year; } }; int main() { Date bd(31, 6, 1352); bd.print_date(); cout << '\n'; cout << bd.get_day() << endl; }
استفاده از توابع معمولی (نه توابع عضو) به عنوان توابع کمکی
bool is_leap_year(int year) { int r = year % 33; return r==1 || r==5 || r==9 || r==13 || r==17 || r==22 || r==26 || r==30; } void Date::set_date(int d, int m, int y) { if (y < 0 || m < 1 || m > 12 || d < 1 || (m < 7 && d > 31) || (m > 6 && m < 12 && d > 30) || (m == 12 && !is_leap_year(y) && d > 29) || (m == 12 && is_leap_year(y) && d > 30)) abort(); day = d; month = m; year = y; }
جدا کردن تابع days_of_month به منظور خوانا کردن برنامه
bool is_leap_year(int year) { int r = year % 33; return r==1 || r==5 || r==9 || r==13 || r==17 || r==22 || r==26 || r==30; } int days_of_month(int m, int y) { if (m < 7) return 31; else if (m < 12) return 30; else if (m == 12) return is_leap_year(y) ? 30 : 29; else abort(); } void Date::set_date(int d, int m, int y) { if (y < 0 || m < 1 || m > 12 || d < 1 || d > days_of_month(m, y)) abort(); day = d; month = m; year = y; }
اضافه کردن یک تابع عضو برای جلوبردن تاریخ به اندازهی یک روز
class Date { public: void inc_one_day(); }; void Date::inc_one_day() { day++; if (day > days_of_month(month, year)) { day = 1; month++; if (month > 12) { month = 1; year++; } } }
مقایسهی تساوی دو تاریخ در قالب یک تابع عضو (equals) و محاسبهی فاصلهی دو تاریخ در قالب یک تابع کمکی (days_between) پیادهسازی شدهاند.
class Date { public: bool equals(Date d); }; bool Date::equals(Date d) { return day == d.day && month == d.month && year == d.year; } int days_between(Date d1, Date d2) { // Assuming d1 is not later than d2 int count = 1; while (!d1.equals(d2)) { d1.inc_one_day(); count++; } return count; } int main() { Date bd(31, 6, 1352); Date today(10, 12, 1391); cout << days_between(bd, today) << endl; }
تبدیل یک رشته به تاریخ بدون درنظر گرفتن خطاهای فرمت ورودی
Date str_to_date(string s) { //TODO: Handle formatting errors int slash_pos = s.find('/'); int d = atoi(s.substr(0, slash_pos).c_str()); s = s.substr(slash_pos + 1); slash_pos = s.find('/'); int m = atoi(s.substr(0, slash_pos).c_str()); int y = atoi(s.substr(slash_pos + 1).c_str()); return Date(d, m, y); } int main() { string s = "12/01/1359"; Date d = str_to_date(s); d.print_date(); str_to_date("10/01/1300").print_date(); }
میتوان از کلاس تاریخ به عنوان تایپ عناصر یک بردار استفاده کرد
#include <vector> class Date { public: }; int main() { Date bd(30, 12, 1387); vector<Date> dates; dates.push_back(bd); dates.push_back(Date(1, 1, 1)); dates[0].print_date(); vector<Date> dates2(100, Date(1,1,1)); }
در این مثال، کلاسی به نام Person تعریف میشود که یکی از فیلدهای آن تاریخ تولد (از نوع Date) است.
class Person { public: Person(string n, int d, int m, int y); Date get_bdate() { return bdate; } string get_name() { return name; } private: string name; Date bdate; }; Person::Person(string n, int d, int m, int y) : bdate(d, m, y) { if (n == "") abort(); name = n; } int main() { vector<Person> vp; vp.push_back(Person("gholam", 2, 7, 1370)); vp.push_back(Person("ghamar", 3, 12, 1368)); vp.push_back(Person("alaleh", 12, 2, 1360)); cout << "Today? "; string today_str; cin >> today_str; Date today = str_to_date(today_str); for (int i = 0; i < vp.size(); i++) if (vp[i].get_bdate().equals(today)) cout << "Happy Birth Day " << vp[i].get_name() << "!\n"; }