КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Cтатичні члени класів і статичні класні функції
Створення і ініціалізація об'єктів, довизначення конструкторів, замовчуваний конструктор, копіювання, поверхневе і глибоке копіювання, ініціалізація і присвоєння, копіювальний конструктор Створення і ініціалізація об'єктів, довизначення конструкторів, замовчуваний конструктор, копіювання, поверхневе і глибоке копіювання, ініціалізація і присвоєння, копіювальний конструктор
Упродовж цього підрозділу ми будемо переписувати визначення декількох класів, наводячи в них все більше лоску. Один з цих класів
class Date { int _day, _month, _year; public: void showDate(); } void Date::showDate() { cout<<_day<<':'<<_month<<':'<<_year<<endl; }
Поки що з цим класом можна зробити небагато чого, наприклад, в результаті виконання програми
int main() { Date t; t.showDate(); return 0; }
одержимо, швидше всього, три незрозумілих числа. Компілятор для проформи доповнить клас замовчуваним конструктором з порожнім тілом. Визначенням Date t конструктор викличеться, буде створений, але не ініціалізований об'єкт t з усіма його атрибутами і методами. Корисно було б подумати, як проініціалізувати атрибути. Ясно, що звичайна ініціалізація виду int _day=1; не підходить. Ініціалізацією атрибутів займається конструктор, оскільки створення об'єкту відбувається динамічно і тому не підконтрольне компілятору. Доповнимо клас конструктором
Date:: Date (int d,int m, int y) { _day=d; _month=m; _year=y; }
або трохи іншим, у якому значення атрибутів задаються ініціалізацією, а не присвоєнням,
Date:: Date (int d, int m, int y): _day(d), _month(m), _year(y) { };
але не обома одночасно. та відповідно інтерфейс
class Date { int _day, _month, _year; public: Date (int d, int m, int y); void showDate(); }
Тепер визначення Date t; стане неможливим. Клас містить власний конструктор, а тому компілятор не стане генерувати замовчуваний конструктор. Приклад вживання класу доведеться переписати на зразок
int main() { Date t(31,1,2003); t.showDate(); return 0; }
Але ж визначення Date t; не було таким вже безглуздим. В такий спосіб можна було б визначати яку-небудь задану дату, наприклад, сьогоднішню. Так в класі Date може з'явитися ще один конструктор
Date:: Date () { // Деталі реалізації системного часу в додатку TIMES.C struct tm * today =new tm; time_t timer;
time(&timer); today = gmtime(&timer);
_day = today->tm_mday; _month = ++(today->tm_mon); _year = today->tm_year+=1900;
cout<<”Сьогодні ” <<today->tm_mday<<':' <<today->tm_mon<<':' <<today->tm_year<<endl; }
Можливі інші варіанти: Date (int d, int m) — дата в поточному році; Date (int d) — день в поточному році і поточному місяці; Date (const char *cdate) — дата, задана у символьному форматі, наприклад, May 03 2003. Подумайте, як реалізувати останній конструктор.
Тепер ми можемо створювати дати різними способами
Date today; Date t(31, 1, 2003); Date s(31, 1); Date u(31); Date v(”Jan 31 2003”); Date w = u; Date x (w); Date y; y = x;
Дві останні ініціалізації та присвоєння реалізуються компілятором шляхом поверхневого поатрибутного копіювання об'єктів. Його можна запрограмувати явно, використовуючи ще один тип конструктора, що зветься конструктором копіювання (copy constructor)
Date::Date (const Date& baseDate) { cout<<"Copy constructor Date "; _day = baseDate._day; _month = baseDate._month; _year = baseDate._year; }
Для нашого випадку досить поатрибутного конструктора копіювання, але наступний приклад покаже проблеми, що виникають при поверхневому копіюванні. Поки що підведемо попередні підсумки, ще раз переписавши інтерфейс
class Date { int _day, _month, _year; public: Date (int d, int m, int y); Date (int d, int m); Date (int d); Date (); Date (const char *cdate); Date (const Date&); void showDate(); }
Розглянемо приклад, для якого поверхневого копіювання недостатньо
class RandomVector { int size; int *v; int position; public: RandomVector(int s); RandomVector(const RandomVector&); ~RandomVector(); };
Клас вектору випадкових величин RandomVector призначається для підтримки статистичних експериментів. Генерується випадкова вибірка v заданої довжини size, в якій потім атрибут position використовується як індекс поточного елементу.
RandomVector::RandomVector(int s): size(s), position(0) { v= new int[size]; for(int i=0; i< } *(v+i)="rand();" i++)> Оскільки в класі використовується динамічна пам'ять, потрібен явний деструктор
RandomVector::~RandomVector () { delete [] v; }
Копіювальний конструктор повинен забезпечувати глибоке копіювання, яке знову ж потребує динамічної пам'яті
RandomVector:: RandomVector (const RandomVector& base):
size(base.size), position(base.position) { v=new int[size]; for(int i=0; i< } *(v+i)="*(base.v+i);" i++)> Ось приклади використання випадкових векторів
RandomVector u1(100); //Звичайний конструктор RandomVector u2=u1; //Конструктор копіювання
А от із спроби присвоїти значення одного вектора іншому нічого доброго не вийде
RandomVector u3(100); u3 = u2; //Error
Тепер доведеться ще довизначити присвоєння, застосувавши у ньому глибоке копіювання (детальніше про довизначення операторів йтиметься у підрозділі 5.8) та відповідно поповнивши інтерфейс оголошенням присвоєння
RandomVector& RandomVector::operator=(const RandomVector& t) { if (size!=t.size) { delete[]v; size=t.size; v=new int[size]; } position=t.position; for(int i=0; i<size; i++) *(v+i)=*(t.v+i); return *this; }
Як бачимо при ініціалізації та присвоєнні об'єктів відбувається тонка робота з пам'яттю. Корисно уявляти собі місце розташування кожного об'єкту абсолютно точно.
Дата добавления: 2014-01-04; Просмотров: 624; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |