Студопедия

КАТЕГОРИИ:


Архитектура-(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;

}

 

 

Як бачимо при ініціалізації та присвоєнні об'єктів відбувається тонка робота

з пам'яттю. Корисно уявляти собі місце розташування кожного об'єкту абсолютно

точно.

 

 

<== предыдущая лекция | следующая лекция ==>
Класи і об'єкти, члени класів | Cтатичні члени класів і статичні класні функції
Поделиться с друзьями:


Дата добавления: 2014-01-04; Просмотров: 600; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.034 сек.