Здавалка
Главная | Обратная связь

Но одно из основных достоинств класса заключается в запрещении доступа к данным, что упрощает поддержку.



В большинстве случаев вызовы функций-членов вместо прямого доступа к данным-членам заметно сказываются на быстродействии программы.

С++ позволяет объявлять классы с встраиваемыми функциями-членами. Хотя, встраиваемые функции-члены используются точно так же, как и другие функции, в скомпилированном коде они не вызываются. Вместо этого встраиваемые функции – члены вставляются непосредственно в скомпилированную программу (рис. 2.3)

 

Рис.2.3. Встраиваемые функции-члены вставляются непосредственно в программный код

 

Листинг 2.9 заново объявляет класс TTime с использованием нескольких встраиваемых функций-членов (строки 14 и 17-22).

 

Листинг 2.9. (новое объявление касса TTime с встроенными функциями членами )

1:// time3.h –Объявление класса TTime

2:

3: #ifndef_ _ TIME3_H

4: #define _ _TIME3_H 1

// Предотвращение нескольких

// #include

5:

6: #include<iostream.h>

7: #include <time. h>

8: #include<string.h>

9:

10: class Ttime {

11: private:

12: long dt; // Дата и время – в //секундах от января 1970 года

13: public:

//встроенная функция-член

14: void Display(void) { cout << ctime(&dt); }

15: void GetTime(int &m, int &d, int &y, int &hr, int &min);

16: void SetTime(int m, int d, int y, int hr, int min);

//встроенная функция-член

17: char *GetTime(void)

18: {

// ctime() для преобразования даты и времени в строку ASCII

19: char *cp = strdup( ctime(dt));

20: return cp;

21: }

22: void ChangeTime(long nminutes) {dt += (nminutes * 60); }

23: };

24:

25: #endif // _TIME3_H

 

Листинг 2.10. Time3.CPP (реализация невстраиваемых функций класса TTime)

1://time3.cpp-Реализация класса Ttime

2:

3: #include <dos.h>

4: #include “time3.h”

5:

6: // Возвращает текущие данные – члены дату и время

7: void TTime : : GetTime(int &m, int &d, int &y, int &hr, int &hr, int &min)

8: {

9: struct date ds;

10: struct time ts;

11:

12: unixtodos(dt, &ds, &ts)

13: y = ds.da_year;

14: m = ds.da_mon;

15: d = ds.da_day;

16: hr = ts.ti_hour;

17: min = ts.ti_min;

18: }

19:

20: // Устанавливает член dt

21: void TTime : : SetTime(int m, int d, int y, int hr, int min)

22: {

23: struct date ds;

24: struct time ts;

25:

26: ds.da_year = y;

27: ds.da_mon = m;

28: ds.da_day = d;

29: ts.ti_hour = hr;

30: ts.ti_min = min;

31: ts.ti_sec = 0;

32: ts.ti_hund = 0;

33: dt = dostounix(&ds, &ts);

34: }

 

Поскольку использование встраиваемых функций-членов не отличается от использования обычных функции членов, основная программа осталась без изменений.

 

Листинг 2.11 идентичен APPOINT2.CPP за исключением того, что в строке3 теперь включается заголовочный фай TIME3.H.

 

Листинг 2.11. APPOINT3.CPP (отображение примера календаря встреч)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time3.h”

4:

5: main()

6: {

7: Ttime appointment;

8:

9:appointment.SetTime(7,21,1996,8,30);

10: for (int slots = 1; slots <= 17; slots++) {

11: appointment. Display();

12: appointment. ChangeTime(30);

13: }

14: return 0;

15: }

 

 

Как и в случае с обычными встроенными функциями, С++ может и не вставить функцию-член непосредственно в скомпилированный код. Например, если встраиваемая функция-член слишком сложна, компилятор может решить скомпилировать ее как обычную функцию-член.

Большинство функций-членов объявляются непосредственно в классе, как это показано в строке 14 листинга 2.9. вы можете объявить встраиваемую функцию-член с помощью ключевого слова inline в модуле реализации класса.

Например, для преобразования GetTime()из Ttime во встраиваемую функцию, вы можете изменить реализацию функции в листинге 2.10 следующим образом:

inline void TTime::GetTime(int &m, int &d, int &y, int &hr, int &min)

{

}

поставив inline пред именем функции, можно и не добиться желаемого результата, поскольку реализация встраиваемых функций-членов должна быть доступна компилятору до того, как эта функция будет вызвана. В большинстве случаев встраиваемые функции-члены лучше всего распознаются, когда они объявлены непосредственно в классе.

 

Перегруженные функции-члены

Перегруженные функции-члены особенно полезны, когда необходимо несколько параметров (а не все) функции-члена.

Например, в текущей функции SetTime() класса TTime необходимо пять параметров. Для того, чтобы установить дату и время: 15 января 1997 года, 11:45, надо написать

TTime anytime;

anytime.SetTime(1, 15, 1997, 11, 45);

 

Предположим, надо установить только дату, при этом время класса по умолчанию равно текущему.

На данный момент инициализировать подобным образом TTime не так-то просто.

Перегрузка SetTime() с различным числом параметров дает возможность в программе передавать произвольное число аргументов, как в следующем выражении

anyTime.SetTime(1, 15, 1997)

В листинге 2.12 проводится новый класс TTime и несколько перегруженных функций-членов SetTime(). В заголовке TIME4.H содержатся только объявления и, следовательно, их нельзя скомпилировать. Следующие два листинга включают TIME4.H c его объявлением класса.

Листинг 2.12 TIME4.H ( с перегруженными функциями- членами)

1://time4.h-Объявление класса TTime

2:

3: #ifndef _ _TIME4_H

4: #define _ _TIME4_H 1

// Предотвращение нескольких #include

5:

6: #include <iostream.h>

7: #include <time.h>

8: #include <string.h>

9:

10: class TTime {

11: private:

12: long dt; // Дата и время – в //секундах от 1 января 1970 года

13: public:

14: void Display(void) { cout << ctime(&dt); }

15: void GetTime(int &m, int &d, int &y, int &hr, int &min);

// В строках 16-21 объявляется шесть //перегруженных функций-членов SetTime()

16: void SetTime(int m, int d, int y, int hr, int min);

17: void SetTime(int m, int d, int y, int hr);

18: void SetTime(int m, int d, int y);

19: void SetTime(int m, int d);

20: void SetTime(int m);

21: void SetTime (void);

22: char * GetTime(void);

23: {

24: char *cp = strdup(ctime (td));

25: return cp;

26: }

27: void ChangeTime(long nminutes) { dt += (nminutes * 60); }

28: };

29:

30: #endif // _ TIME4_H

 

В строках 16-21 объявляется шесть перегруженных функций-членов SetTime(). Все они имеют одинаковое имя и отличаются хотя бы одним параметром – таково минимальное требование, чтобы компилятор мог их различить. И хотя все функции-члены имеют одинаковое имя, их тела должны быть реализованы раздельно, как это показано в листинге 2.13.

 

Листинг 2.13. TIME4.CPP (реализация перегруженных функций-членов)

1://time4.cpp- реал-ция класса TTime

2:

3: #include <dos.h>

4: #include “time4.h”

5:

6: // Возвращает текущие данные-//члены дату и время

7: void TTime::GetTime(int &m, int &d, int &y, int &hr, int &min);

8: {

9: struct date ds;

10: struct time ts;

11:

12: unixtodos(dt, &ds, &ts );

13: y = ds.da_year;

14: m = ds.da_mon;

15: d = ds.da_day;

16: hr = ts.ti_hour;

17: min = ts.ti_min;

18: }

19:

20: // Устанавливает член dt

21: void Ttime : : SetTime(int m, int d, int y, int hr, int min)

22: {

23: struct date ds;

24: struct time ts;

25:

26: getdate(&ds); // Получение текущих даты и времени

27: gettime(&ts);

28: if (y >= 0) ds.da_year = y;

29: if (m >= 0) ds.da_mon = m;

30: if (d >= 0) ds.da_day = d;

31: if (hr >= 0) ts.ti_hour = hr;

32: if (min >= 0) ts.ti_min = min;

33: ts.ti_sec = 0;

34: ts.ti_hund = 0;

35: dt = dostounix(&ds, &ts);

36: }

37:

38: void TTime : : SetTime(int m, int d, int y, int hr)

39: {

40: SetTime(m, d, y, hr, -1);

41: }

42:

43: void TTime : : SetTime(int m, int d, int y)

44: {

45: SetTime(m, d, y, -1, -1);

46: }

47:

48: void TTime::SetTime(int m, int d)

49: {

50: SetTime(m, d, -1, -1, -1);

51: }

52:

53: void TTime : : SetTime(int m)

54: {

55: SetTime(m, -1, -1, -1, -1);

56: }

57:

58: void TTime : : SetTime(void)

59: {

60: SetTime(-1, -1, -1, -1, -1);

61: }

 

Если today - объект класса TType, оператор

today.SetTime(1, 15, 1998, -1, -1);

устанавливает дату, хранящуюся в today, равной 15 января 1998 года, но с текущим временем, поскольку эти два аргумента установлены равными -1.

Т.к. функция перегружена, можно написать

today.SetTime(1, 15, 1998);

 

Например, оператор

today.SetTime();

вызывается перегруженную функцию-член SetTime(), реализованную в строках 58-61 и не имеющую аргументов, которая, в свою очередь, вызывает версию с пятью аргументами для установки в today системной даты и времени.

 

В листинге 2.14 демонстрируется использование перегруженных функций-членов TTime.

 

Листинг 2.14 OVERMF.CPP (использование перегруженных функций-членов)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time4.h”

4:

5: main()

6: {

7: TTime ap;

8:

9: ap.SetTime();

10: ap.Display();

11: ap.SetTime(8);

12: ap.Display();

13: ap.SetTime(8, 1);

14: ap.Display();

15: ap.SetTime(8, 1, 1996);

16: ap.Display();

17: ap.SetTime(8,1,1996,8);

18: ap.Display();

19:ap.SetTime(8,1,1996,8,30);

20: ap.Display();

21: return 0:

22: }

 

Д/з ??? какое время на дисплее

 

Параметры функций-членов по умолчанию

Многочисленные перегруженные функции-члены, подобные приведенным в строках 16-21 листинга 2.12, полезны, но зачастую приводят к путанице в коде.

В некоторых случаях параметры функций-членов по умолчанию помогают сократить количество функций-членов, необходимых для поддержки вызовов с различным числом аргументов.

Параметры функций-членов по умолчанию используются в объявлении классов.

 

В листинге 2.15, приводится новая версия функции SetTime() класса TTime, использующая параметры по умолчанию.

Листинг 2.15 TIME5.H (новая версия класса TTime c использованием параметров функций-членов по умолчанию)

1://time5.h-объявление класса TTime

2:

3: #ifndef __TIME5_H

4: #defaine__TIME5_H 1

// Предотвращение нескольких #include

5:

6: #include <iostream.h>

7: #include <stdio.h>

8: #include <string.h>

9:

10: class TTime {

11: private:

12: long dt; // Дата и время –в //секундах от 1 января 1970 года

13: public:

14: void Display(void) { cout << ctime(&dt); }

15: void GetTime(int &m, int &d, int &y, int &hr, int &min);

// Каждому из параметров //SetTime() присваивается значение //по умолчанию -1, //использовавшееся для //идентификации неуказанных //параметров в вызове этой //функции-члена.

void SetTime(int m = -1, int d = -1, int y = -1,

int hr = -1, int min = -1);

18: char *GetSTime(void)

19: {

20: char *cp = strdup(ctime(&dt));

21: return cp;

22: }

23: void ChangeTime(long nminutes) {dt += (minutes *60); }

24: }

25:

26: #endif // __TIME5_H

 

Каждому из параметров SetTime() в строках 16-17 присваивается значение по умолчанию -1, использовавшееся для идентификации неуказанных параметров в вызове этой функции-члена.

 

Значения параметров по умолчанию должны следовать за всеми прочими параметрами в объявлении функции-члена.

В данном объекте класса TTime с именем today оператор

today.SetTime(1,15, 1998);

 

передает дату 15 января 1998 года первым трем параметрам SetTime(). Поскольку неуказанные аргументы принимают значения по умолчанию, последние два аргумента неявным образом устанавливаются равными -1,

// компилируется так, как если бы //был написан

today.SetTime(1, 15, 1998, -1, -1);

 

Новая реализация класса TTime значительно проще в сравнении с перегрузкой функций-членов SetTime().

В листинге 2.16 приводится результат.

Значения функций-членов по умолчанию не приводятся в заголовке функции (при реализации). Значения по умолчанию могут присутствовать только в объявлении функции-члена.

 

 

Листинг 2.16 TIME5.CPP ( реализация упрощенного класса TTime)

1://time.cpp–реализация класса TTime

2:

3: #include <dos.h>

4: #include “time5.h”

5:

6: // Возвращает текущие //данные-члены даты и время

7: void::GetTime(int &m, int &d, int &y, int &hr, int &min)

8: {

9: struct date ds;

10: struct time ts;

11:

12: unixtodos(dt, &ds, &ts);

13: y = ds.da_year;

14: m = ds.da_mon;

15: d = ds.da_day;

16: hr = ts.ti_hour;

17: min = ts.ti_min;

18: }

19:

20: // Устанавливает член dt

21: void TTime : : SetTime(int m, int d, int y, int hr, int min)

22: {

23: struct date ds;

24: struct time ts;

25: //Получение текущих даты и

// времени

26: getdate(&ds);

27: gettime(&ts);

28: if (y >= 0) ds.da_year = y;

29: if (m >= 0) ds.da_mon = m;

30: if (d >= 0) ds.da_day = d;

31: if (hr >= 0) ts.ti_hour = hr;

32: if (min >= 0) ts.ti_min = min;

33: ts.ti_sec = 0;

34: ts.ti_hund = 0;

35: dt = dostounix(&ds, &ts);

36: }

 

В листинге 2.17 используется новый класс TTime. демонстрируется, что в этом случае

параметры функций-членов по умолчанию позволяют использовать переменное число аргументов в вызовах функции SetTime().

 

Конечно результат такой же, как и в приведенном ранее примере перегрузки, но реализация класса стала намного проще.

 

 

Листинг 2.17 DEFAULT.CPP (использование параметров функций-членов по умолчанию)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time5.h”

4:

5: main()

6: {

7: TTime ap;

8:

9: ap.SetTime();

10: ap.Display();

11: ap.SetTime(8);

12: ap.Display();

13: ap.SetTime(8, 1);

14: ap.Display();

15: ap.SetTime(8, 1,1996);

16: ap.Display();

17: ap.SetTime(8,1,1996,8);

18: ap.Display();

19: ap.SetTime(8,1,1996,8,30);

20: ap.Display();

21: return 0:

22: }

%%%%%%%%%%%%%%%%%

Конструкторы и деструкторы

До сих пор инициализация объекта класса происходила при его создании.

Возьмем любой из предыдущих классов TTime. Объявление

TTime anytime;

создает объект класса anytime типа TTime, но не инициализирует его данные-члены.

 

Если забыли инициализировать объект класса, оператор

аnytime.display();

скорее всего выведет всякий мусор или, по крайней мере, неверную дату и время.

 

В классах м.б. объявлено несколько конструкторов для автоматической инициализации объекта класса при его создании, исключая т.о. возможность ошибок, вызванных использованием неинициализированных данных.

В классах также может быть объявлен (но только один) деструктор, вызываемый для очистки при выходе объекта класса из области видимости.

Конструкторы и деструкторы похоже на обычные функции-члены, но они реже вызываются непосредственно в операторах программы.

С++ автоматически вызывает конструкторы и деструкторы для инициализации и очистки объектов класса.

 

В листинге 2.18 объявляться еще одна версия класса TTime. Новый класс имеет два конструктора для инициализации заново созданных объектов класса TTime. В нем также имеется деструктор для очистки старых объектов класса TTime, выходящих из области видимости.

 

Листинг 2.18. TIME6.H (объявление класса TTime с конструкторами и деструктором)

1://time6.h- объявление класса TTime

2:

3: #ifndef __TIME6_H

4: #defaine__TIME6_H 1

//Предотвращение нескольких #include

5:

6: #include <iostream.h>

7: #include <stdio.h>

8: #include <string.h>

9:

10: class TTime {

11: private:

12: long dt; // Дата и время – //в секундах от 1 января 1970 года

13: char *dts; // Представление //даты и времени в виде строки

//адрес строкового представления даты и времени

14: void DeleteDts(void);

// Удаляет указатель dts

15: public:

// конструктор

//выз-ся по умолчанию, т.к. без пар-ров

16: TTime();

// перегруженный конструктор

17: TTime(int m, int d = -1, int y = -1,

18: int hr = -1, int min = -1);

19: ~TTime(); // Деструктор

20: void Display(void) { cout << ctime(&dt); }

21: void GetTime(int &m, int &d, int &y, int &hr, int &min);

22: void SetTime(int m = -1, int d = -1, int y = -1,

23: int hr = -1, int min = -1);

24: const char *GetSTime(void);

25: void changeTime(long nminutes)

26: { dt += (nminutes *60); DeleteDts(); }

27: };

28:

29: #endif //__TIME6_H

 

Конструкторы объявлены как функции-члены, не возвращающие никаких значений, с произвольным числом параметров любого типа (за исключением классов, которым принадлежат эти конструкторы). Конструкторы, как правило, объявляются в открытой секции, но могут определяться в любом месте класса.

Они всегда имеют такое же имя, как в классе, для которого объявляются. Они не всегда могут быть скомпилированы встраиваемыми.

 

В строке 16 объявляется TTime() в качестве конструктора класса TTime. Поскольку конструктор объявляется без параметров, он вызывается по умолчанию. В строках 17-18 объявляется второй перегруженный конструктор для TTime. Этот конструктор имеет одинаковое с классом имя, но на этот раз он объявлен с пятью целочисленным параметрами, из которых последние четыре передают значения по умолчанию -1. В TTime также объявлен в строке 19 деструктор.

В дополнение к конструкторам и деструктору новый класс TTime имеет еще два отличия. В строке 13 добавлен второй закрытый член класса – символьный указатель dts. Этот указатель содержит адрес строкового представления даты и времени. Хранение даты и времени в виде символьной строки помогает облегчить управление памятью в классе, а так же может улучить быстродействие программы. В строке 14 добавлена закрытая функция-член DeleteDts(), освобождающая память, на которую указывает dts. Закрытые функции-члены могут вызываться только другими функциями-членами класса и, как и другие закрытые члены, недоступны вне класса. Невозможно в произвольном операторе программы вызвать DeleteDts() и освободить память, на которую ссылается dts. Только члены класса имеют подобную привилегию.

 

реализация TTime в листинге 2.19. Как и в предыдущей версии класса TTime, TIME6.CPP –отдельный модуль, в котором отсутствует функция main(). Далее будет приведен листинг, использующий модуль объявления класса и его реализации.

 

Листинг 2.19. TIME6.CPP (реализация TTime)

1: // time6.cpp -- реализация класса TTime

2:

3: #include <dos.h>

4: #include “time6.h”

5:

6: // Конструктор по умолчанию

7: TTime::TTime()

8: {

9: dts = NULL; // Обнуление //текущей строки

//вызов с аргументами по умолчанию -1

10: SetTime(-1, -1, -1, -1, -1);

11: }

12:

13: // Перегруженный конструктор

14: TTime::TTime(int m, int d, int y, int hr, int min)

15: {

16: dts = NULL; // Обнуление //текущей строки

17: SetTime(m, d, y, hr, min);

18: }

19:

20: // Деструктор

21: TTime::~TTime()

22: {

23: delete dts; // Удаление //строки, хранящейся в объекте

24: }

25:

26: // Удаление указатель dts

27: void TTime::DeleteDts(void)

28: {

29: delete dts; // Удаление строки, //хранящейся в объекте

30: dts = NULL; // Обнуление указатель

31: }

32:

33: // Возвращает текущие данные-//члены дату и время

34: void TTime::GetTime(int &m, int &d, int &y, int &hr, int &min);

35: {

36: struct date ds;

37: struct time ts;

38:

39: unixtodos(dt, &ds, &ts);

40: y = ds.da_year;

41: m = ds.da_mon;

42: d = ds.da_day;

43: hr = ts.ti_hour;

44: min = ts.ti_min;

45: }

46:

47: // Устанавливает член dt

48: void TTime : : SetTime(int m, int d, int y, int hr, int min)

49: {

50: struct date ds;

51: struct time ts;

52:

53: getdate(&ds); // Получение //текущих даты и времени

54: gettime(&ts);

55: if (y >= 0) ds.da_year = y;

56: if (m >= 0) ds.da_mon = m;

57: if (d >= 0) ds.da_day = d;

58: if (hr >= 0) ts.ti_hour = hr;

59: if (min >= 0) ts.ti_min = min;

60: ts.ti_sec = 0;

61: ts.ti_hund = 0;

62: dt = dostounix(&ds, &ts);

63: DeleteDts(); // Удаление //текущей строки

64: }

65:

66:const char *TTime::GetSTime(void)

67: {

68: if (dts) // Возвращает //текущую строку, если она //инициализирована

69: return dts;

// ctime() для преобразования даты и времени в строку ASCII

70: dts = strdup(ctime(&dts));

71: return dts;

72: }

 

В строках 7-11 приводится конструктор TTime по умолчанию – TTime(). Как и в случае всех прочих функций-членов, заголовку реализации предшествует имя класса и оператор разрешения области видимость. Хотя внешний вид заголовка TTime::TTime(), кажется, страдает от зеркального отражения, тем не менее он верно идентифицирует конструктор TTime(), как принадлежащий классу TTime (рис. 2.4).

Программирование внутренних операторов конструктора ничем не отличается от программирования других функций-членов или обычных функций. Конечно. Обязанности типичного конструктора ограничены присваиванием начальных значений данным-членам класса, выделением памяти, используемой объектом класса, и т.д. В данном случае в строке 16 символьный указатель dts устанавливается равным NULL, это значит, что указатель еще не ссылается на строку. Поскольку С++ автоматически вызывает конструктор для инициализации объекта класса TTime, следовательно, все такие объекты гарантированно имеют инициализированный указатель dts. Конструктор также вызывает функцию-член SetTime() с аргументами по умолчанию -1 (строка 10), устанавливая таким образом в объекте класса текущие дату и время.

 

 

 

Рис. 2.4. детали и части конструктора

 

Второй перегруженный конструктор приводится в строках 14-18. похоже на конструкторе по умолчанию, но объявлен с параметрами даты и времени и может использоваться для инициализации значений объекта класса. Перегруженные конструкторы похожи на перегруженные функции-члены.

В любом классе можно объявить столько конструкторов, сколько потребуется, при условии, что они отличаются хотя бы одним своим параметром.

Конструкторы должны иметь одинаковое имя с классом, в котором они определены и, следовательно, перегружаются по определению.

 

Использование конструкторов

Не все классы нуждаются в конструкторах, но в большинстве из них определен хотя бы один. В иных классах может быть дюжина конструкторов и даже более. Цель конструкторов обеспечить ясно определенную инициализацию объектов класса.

 

В листинге 2.20 демонстрируется инициализация объектов класса TTime конструкторам TTime().

 

Листинг 2.20. CONSTRUC.PP (использование конструкторов TTime)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

// В строках 7-12 объявляются //шесть объектов класса TTime и //инициализируются

7: TTime t1;

8: TTime t 2(8);

9: TTime t3(8, 1);

10: TTime t4(8, 1, 1996);

11: TTime t5(8, 1, 1996, 8);

12: TTime t6(8, 1, 1996, 8, 30);

13:

14: t1.Display();

15: t2.Display();

16: t3.Display();

17: t4.Display();

18: t5.Display();

19: t6.Display();

20: return 0;

21: }

 

В строках 7-12 объявляются шесть объектов класса TTime. С++ автоматически вызывает конструктора класса при его создании. Например, когда программа выделяет пространство для t1, как это объявлено в строке 7, вызывается конструктор по умолчанию для инициализации объекта.

В строках 8 -12 объявляются и инициализируются объекты класса, начиная с t2 и заканчивая t6, с указанием явных параметров в круглых скобках. Эти объявления имеют сходства с более ранними примерами, в которых объявлялся объект класса TTime и затем вызывались функции- члены SetTime() для присваивания значении данным-членам объекта. Конечно, с использованием конструкторов вся эта работа автоматически выполняется во время создания объектов.

С помощью конструкторов объекты класса гарантированно инициализируются, что помогает предупредить одну из самых распространенных ошибок в программировании – использование не инициализированных переменных.

 

Попробуйте с помощью встроенного отладчика исследовать, как в приведенном образце программы вызываются различные конструкторы TTime. С начала с помощью меню Project откройте CONSTRUC.IDE, затем выберите CONSTRUC. CPP в окне проекта для того, чтобы открыть этот файл. Поместите курсор на первый оператор mine() и нажмите <F5> для установки точки прерывания на этой строке. Установите также точке прерывания на следующих пяти строках. Все шесть строк должны выделяться на цветном мониторе красным цветом. Нажмите <Ctrl+F9> для компиляции и запуска программы. Выполнение прервется на первой точке прерывания. Для того чтобы определить, какой конструктор вызывается в операторе, нажмите <F9> для входа в тело конструктора. Это приведет вас к конструктору по умолчанию. Нажмите <Ctrl+F9> для продолжения выполнения программы до следующей точки останова и затем опять нажмите <F7> для входа в вызов функции, на этот раз вы попадете во второй конструктор класса. Повторяйте эти действия до тех пор, пока программа не начнет отображение.

 

 

Использование деструкторов

Еще один пример программы демонстрирует использование класса TTime из TTIM6.H и TIME6.CPP (листинги 2.18 и 2.19), а также показывает, как используется деструктор для очистки объекта класса при его выходе из области видимости.

 

Листинг 2.21 DESTRUC.CPP (использование деструктора TTime )

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: void f(void);

6:

7: main()

8: {

9: f();

10: return 0;

11: }

12:

13: void f(void)

14: {

// локальный объект today класса TTime

15: TTime today;

// т.к. локальный автоматический объект создается вместе с вызовом функции, в которой он объявлен, С++ вызывает для today конструктор TTime() по умолчанию

// локальный символьный указатель sp

16: const char *sp;

17:

// вызовы GetSTime() будут использовать созданную ранее строку

// Это сокращает количество выделений пространства в динамически распределяемой //области памяти для строкового предоставления даты и времени

18: sp = today.GetSTime();

19: cout << “First time: ” << sp;

20: sp = today.GetSTime();

21: cout << “Second time: ” << sp;

22: }

 

Функция main() в DESTRUC.CPP вызывает другую функцию f(), приведенную в строках 13-22. Внутри функции в строке 15 объявляется автоматический объект класса TTime today, локальный в области видимости функции. Поскольку локальный автоматический объект создается вместе с вызовом функции, в которой он объявлен, С++ вызывает для today конструктор TTime() по умолчанию в качестве части кода, выполняемого функцией при запуске. Подобная операция выполняется всякий раз при вызове функции. (вы можете проверить этот факт из интегрированной среды с помощью встроенного отладчика.)

В строках 18-21 вызывается функция-член GetSTime() для объекта класса today. Результат этой функции сохраняется в локальном символьном указателе sp. Вернемся к листингу 2.19, в котором приводится реализация GetSTime() (строки 66-72). Функция-член сначала проверяет, не содержит ли член dts нуль. Если нет, то возвращается dts, иначе вызываются strdup() и ctime() для преобразования текущей даты и времени в символьную строку, с сохранением адреса строки в символьном указателе dts _ закрытом члене класса. Таким образом, последующие вызовы GetSTime() будут использовать созданную ранее строку. Это сокращает количество выделений пространства в динамически распределяемой области памяти для строкового предоставления даты и времени, уменьшает фрагментацию динамически распределяемой области и улучшает быстродействия программы.

Поскольку класса TTime владеет указателем dts, ссылающимся на выделенный блок памяти, класс должен аккуратно управлять распределением этой памяти. Объект типа TTime не должен выходить из области видимости без освобождения выделенной этому объекту памяти, иначе это приведет к ошибкам, связанным с нехваткой памяти. Кроме того, если дата и время объекта класса TTime изменились (на пример, с помощью обращения к ChangeTime() и SetTime()), то не нулевой указатель dts должен быть удален и установлен равным 0, таким образом он будет выделен заново в следующем вызове GetSTime().

Вернемся к TIME6.H (листинг 2.18) и рассмотрим строку 19, в которой объявляется деструктор для класса TTime. Деструкторы обычно объявляется в открытой секции класса, но могут и не объявляться вовсе. Класс может иметь не более одного деструктор с именем класса, в котором он объявлен (как и все конструкторы). Только объявлению деструктора предшествует тильда (~), которая используется в математике для обозначения разности. Деструкторы – антиподы конструкторов: то, что создано конструктором, может быть уничтожено деструктором.

Реализация деструктора ничем не отличается от других функций-членов. Вы можете усовершенствовать код, объявив деструктора встраиваемым. В листинге 2.19 в строках 21-24 приводится реализация деструктора класса TTime:

TTime::~TTime()

{

delete dts ; // Удаление строки, ранящейся в объекте

}

Так же, как конструкторы и функции-члены, имя деструктора TTime() предваряется именем класса и оператором разрешения области видимости TTime::, что идентифицирует деструктор как член класса TTime.единственный оператор в деструкторе TTime удаляет dts, (можно не проверять dts на содержание ненулевого значения; оператор delete проигнорирует нулевые аргументы-указатели.)

Если объект класса выходит из области видимости, С++ автоматически вызывает конструктор объект класса, если таковой имеется. Это дает объекту удобную возможность для самоочистки, например удаления памяти, выделенной конструктором или функцией-членом.

 

Помните: конструкторы создает, деструкторы разрушают. Класс может иметь много конструкторов, следовательно, программа может создавать объекты различными способами. Конечно, класс может иметь не более одного деструктора, который вызывается автоматически при уничтожении объекта или при выходе его из области видимости. Если необходимо по-разному уничтожать объекты, деструктор может вызывать функции-члены, использовать оператор switch и другие средства для адекватных действий в различных ситуациях.

 

“Жизнь” объекта

объекты класса могут быть глобальными или локальными в функции.

Как и переменные обычных типов, объекты класса могут также адресоваться указателями и ссылками.

Думайте о классах, как о новых типах данных, и используйте их соответствующим образом, так же, как и переменные других типов.

Природа объекта, а именно: является ли он глобальными, локальным, адресуемым указателем и т.д. - влияет на то, когда будут вызываться конструкторы и деструктор этого объекта класса.

При создании объекта С++ автоматически вызывает конструктор этого объекта по умолчанию или другой конструктор, который вы укажете в объявлении объекта.

Когда объект выходит из области видимости, С++ вызывает его конструктор.

На рис. 2.5 на временном отрезке представлены все эти действия с отметкой типичных событий, происходящих в жизни объекта.

Следующие замечания помогут прояснить, когда вызывается конструкторы и деструкторы для объектов классов различных типов.

 

 


Рис. 2.5. события, обычно происходящие с объектами во время его существования

 

Глобальные объекты класса

Конструктор глобальных объектов класса вызывается до начала выполнения функции main().

Это обеспечивает инициализации всех глобальных объектов до формального начала выполнение программы.

ПРИМЕР:

При использовании классаTTime (листинг 2.18 и 2.19) глобальное объявление

TTime today;

Создает глобальный объект today класса TTime. До вызова main() C++ вызывает для today конструктор TTime по умолчанию, который устанавливает в объекте текущую дату и время.

Для инициализации глобального объекта класса TTime каким-либо определенным датой и времени следует использовать следующее объявление:

TTime sTime(9, 4, 1953, 10, 45);

Наличие списка инициализаторов в круглых скобках С++ вызовет перегруженный конструктор TTime (строки 17-18 листинга 2.18), который инициализирует stime значением даты и времени 4 сентября 1953 года, 10:45.

это действие выполнится до того, как будет вызвана main().

 

Деструкторы глобальных объектов класса вызываются как обычно в качестве части кода завершения программы, после отработки функций завершения, заданных вызовами функции exit(). Деструкторы не вызываются, если программа заканчивается с помощью обращения к abort().

 

Локальные объекта класса

Автоматические объекты класса, объявленные локальными в функции, создаются вместе с вызовом функции и уничтожается с ее завершением.

Как и переменных обычных типов, данные-члены автоматического объекта класса сохраняются в стеке.

В функции

void anyFunction(void)

{

TTime now;

// Инициализируется при каждом //вхождении в функцию

….

}

по умолчанию вызывается конструктор TTime для инициализации объекта класса now текущими датой и временем каждый раз, когда вызывается функция.

Когда функция завершает работу, С++ вызывает деструктор TTime для объекта now.

(что дает объекту возможность “убрать” за собой до того, как он выйдет из видимости.)

При вызове exit() деструкторы глобальных объектов классов вызывается как обычно, а деструкторы любых существующих автоматических переменных, локальных в функции (включая и те, которые локальны в main()), не вызываются.

 

Указатель на объекты

Указатели могут ссылаться на динамические объекты класса, пространство для которых обычно выделяется в куче с помощью new.

ПРИМЕР:

// указатель pToday на объект класса //типа TTime

TTime *pToday;

Это объявление м.б. как глобальным в функции.

 

// инициализация указателя pToday до

//его использования с помощью new

pToday = new TTime;

// с помощью оператора new выделяется пространство в куче для объекта типа TTime.

Адрес первого байта этого объекта присваивается pToday.

С++ вызывает конструктор объекта по умолчанию, который инициализирует объекта текущими датой и временем.

 

Для использования другого конструктора добавьте параметры после имени класса.

для выделения памяти для объекта TTime и инициализации его с помощью вызова конструктора с пятью параметрами :

pToday=new Time(9, 4, 1953, 10,45);

 

 

использование указателей на объекты класса для ссылки на член адресуемого объекта можно

· с помощью оператора ->

· оператора *

 

 

Указатели на объекты класса используются в точности так же, как и указатели на объекты других типов.

Пример:

//вывод даты и времени объекта класса

//TTime, на который ссылается pToday:

pToday->Display();

 

Пример:

Sp = ( *pToday).GetSTime();

//присваивание переменной sp (которая //объявлена, как const char *sp;) результата функции-//члена GetSTime() для объекта //класса, на который ссылается //pToday.

Sp = pToday->GetSTime();

//легче,выполняется аналогично .

 

С++ вызывает деструкторы динамических объектов класса при их удалении. Пример:

delete pToday;

//удаление объекта, на который //ссылается pToday, освобождение //памяти этого объекта в куче.

//перед разрушением объекта С++ //вызывает деструктор класса.

 

Не путайте жизнь указателя с жизнью объекта, на который он ссылается. Глобальный указатель существует до тех пор, пока программа не завершится, но он может ссылаться на множество объектов класса, создаваемых с помощью new и удаляемых с помощью delete. Аналогично, автоматически указатели, объявленные локальными в функции, создаются при выполнении функции и уничтожаются при ее завершении. Но объекты, на которые ссылаются указатели, имеют глобальную область действия и должны удалятся явным образом.

В функции f(), если вы вызовете new для создания объекта в куче, этот объект останется в памяти даже после завершения функции. Вы должны явным образом удалять любой подобный объект, если вы не хотите, чтобы он оставался в памяти после возврата из функции.

 

Ссылочные объекты

Обычно ссылки объявляются в качестве параметров функции. На практике они редко используются так, как описано в этом разделе.

 

Объекты класса могут объявляться как ссылки. Предположим, вы объявили глобальный объект класса TTime:

TTime today;

// глобальный объект today

Позже, в программе, вы можете объявить ссылку на today следующим образом:

TTime &rToday = today ;

// ссылка на today

Ссылка rToday – алиас для today, и можете использоваться вместо today. Например, каждый из следующих двух операторов выведет дату и время:

rToday.Display();

today.Display();

Поскольку ссылки ссылаются на реально существующие объекты, при входе в область действия ссылки конструктор класса не вызывается и, соответственно, не вызывается деструктор при выходе из области действия ссылки. Эти действия выполняются только при создании и удалении самого объекта.

 

Совет

Обычно ссылки объявляются в качестве параметров функции. На практике они редко используются так, как описано в этом разделе.

 

Объекты-параметры

можно передавать объекты класса, указатели на объекты класса и ссылки на них в качестве аргументов функций.

Классы - это типы данных, и вы можете объявлять параметры функции, имеющие тип классов так же, как и параметры других типов.

1. Пример передачи по значению:

//реализация ф-ции

void anyFunction(TTime t)

// параметр t типа TTime

{

t.Display();

//вызывается функция-член Display() объекта t для вывода даты и //времени, хранящихся в параметре

}

пример:

//вызов ф-ции

// объявление объекта класса TTime

TTime today;

anyFunction(today);

 

Функции также могут объявлять в качестве параметров указатели на класс.

Передача больших по размерам объектов класса функции по значению приводит к выделению пространства нежелательной величины в стеке для таких объектов.

 

В таких случаях предпочтительней параметры-указатели.

 

2. Пример передачи с параметрами-указателями:

 

void anyFunction(TTime *tp)

{

tp->Display();

}

вызов этой ф-ции

anyFunction(&today);

 

3. Пример передачи с с использованием ссылочного параметра (на объект класса TTime):

 

void anyFunction(TTime &tr) // tr—ссылочный параметр

{

tr.Display();

// вызов Display() для объекта, на //который ссылается tr

 

// передача объекта класса TTime

//в качестве ссылочного параметра

anyFunction(today);

 

недостаток ссылочных параметров – такой оператор похож на передачу аргумента today по назначению.

Факт передачи в anyFunction() ссылки на today из текста совершенно не очевиден.

 

Объекты - результаты функций

Функции могут возвращать объекты классов непосредственно в качестве указателей или как ссылки.

1.Пример: функция, возвращает объект класса TTime

 

TTime newTime(void)

{

// Локальный объект t (автоматически инициализированный вызовом конструктора в начале выполнения функции) возвращается непосредственно.

 

TTime t;

return t;

}

//вызов ф-ции

// результат функции newTime() //копируется в anTime

TTime anTime = newTime();

 

Такой подход имеет мало преимуществ

2.Пример: функция, возвращает указатели на объекты класса

 

TTime *newTimeP(void)

{

TTime *P = new TTime;

// выделение и инициализация //объекта

return P;

// возвращение адреса объекта в //качестве результата функции

//объект, на который ссылается этот //указатель, глобальный, сл-но можно вернуть указтель

}

 

//вызов ф-ции

TTime *tp =newTimeP();

//получение нового объекта и //присвоение его адреса указателю tp

 

3.Пример: функция, возвращает ссылки на объекты класса

 

//ссылочная функция для ссылки на //существующий глобальный объект //Ttimetoday:

TTime &newTimeR(void)

{

return today;

}

 

//вызов ф-ции

//объявление ссылки на TTime

//присвоение ей результата //newTimeR()

TTime &tr = newTimeR();

//ccылка tr— псевдоним для today

newTime R().Display();

 

Это полезно в случае, если функция подобная newTimeR(), выполняет операцию поиска с возможным возвратом ссылки на один из нескольких объектов класса TTime, исходя из неких указанных критериев.

 

 

Массивы объектов класса

 

Пример: массив из 10 элементов объектов TTime

TTime tenTimes[10];

//С++ вызывает 10 раз конструктор по умолчанию TTime, //инициализируя таким образом объекты tenTimes[0]-tenTimes[9] //текущими датой и временем

строгое правило: объекты класса, Которые, будут содержать массив, должны иметь конструкторы по умолчанию.

 

Пример 2.22 OB.CPP (массивы и конструкторы по умолчанию)

(используется класс TTime, определенный ранее в TIME6.H)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

//объявляется массив tar из

//шести объектов TTime

7: TTime tar[6];

8:

9: for (int i = 0; i < 6; i++)

// шесть одинаковых дат и времен

10: tar[i].Display();

11: return 0;

12: }

 

Для вызова различных конструкторов, надо явным образом инициализировать каждый элемент массива.

Пример 2.23 OB1.CPP (объявление массивов и альтернативных конструкторов)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

//объекты массива

//инициализируются конструкторами,

//указателями в скобках

7: TTime tar[6] = {

// с помощью вызова конструктора по //умолчанию

8: TTime(),

//вызов перегруженных

// конструкторов

9: TTime(8),

10: TTime(8, 1),

11: TTime(8, 1, 1996),

12: TTime(8, 1, 1996, 8 ),

13: TTime(8, 1, 1996, 8, 30),

14: };

15: for (int i = 0; i < 6; i++)

16: tar[i].Display();

17: return 0;

18: }

 

Нет простого способа инициализировать одни массивы объектов класса с помощью конструктора по умолчанию, а другие с помощью альтернативного конструктора.

Этот прием слишком громоздкий для широкого применения на практике за исключением небольших по размеру массивов.

 

Массивы объектов классов могут также размещаться в куче и адресоваться с помощью указателей.

 

Пример 2.24. OB3.CPP (поддержка динамических массивов объектов класса)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

// tarP - указатель на объект класса //TTime

7: TTime *tarP;

8:

9: tarP = new TTime[6];

// Создание динамического массива

10: for (int i = 0; i < 6; i++)

11: tarP[i].Display();

12: delete[] tarP;

// особая форма delete[]

//вызов всех деструкторов (для //каждого объекта в массиве) при

//удалении динамического массива

// объектов класса

13: return 0;

14: }

 

Замечание

В прошлых версиях С++ необходимо было указывать число элементов вудаляемом массиве объектов класса и вам пришлось бы использовать операторы вида delete[6] tarrayP; для удаления массива из шести объектов класса TTime, на который ссылается tarrayP. Применение этого приема ныне не допускается, и Borland С++ игнорирует любые значения внутри скобок delete[]. Если вы укажете размер массива в скобках, компилятор выдаст вам предупреждение “array size for ‘delete” ignored in function x() ” (Размер массива для delete проигнорирован в функции x()).

 

 

**************************************************************

ИТОГИ

Элементы –поля и методы класса.

Поля – данные класса (данные-члены).

Методы – функции класса (ф-ции члены).

 

сlass <bvz> {

[private:]

<описание скрытых эл-тов >

Public:

<описание доступных эл-тов >

};

 

Поля класса:

· м.б.любого типа;

· м.б. описаны с модификатором const, инициализируются один раз (конструктором) и не м. изменяться;

· м.б. описаны с модификатором static ( не auto, extern, register).

Static-статическая переменная.Время жизни – постоянное. Инициализация – один раз при первом выполнении оператора, инициализирующего переменную. М.б. лок. , глоб.

Auto- автоматическая переменная. Память выделяется в стеке, инициализация – столько раз, сколько нужно. Освобождение – при выходе из блока. Время жизни : от начала описания до конца блока. Для лок-ных – по умолчанию, для глоб. – не исп-ся.

Extern- переменная объявлена в другом месте программы (др. модуль, или дальше в программе). Исп-ся для создания пер-ных, доступных во всех модулях.

Register- аналог Auto. Память выделяется в регистрах процессора

 

ОПИСАНИЕ ОБЪЕКТОВ

Конкретные переменные типа «класс» называются экземплярами класса, или объ­ектами. Время жизни и видимость объектов зависят от вида и места их описания и подчиняются общим правилам C++:

TTime V; // Объект класса TTime с параметрами по

TTime Super(200, 300); // Объект с явной инициализацией
TTime stado[100]: // Массив объектов с параметрами по

TTime *beavis = new monstr (10); // Динамический объект

//(второй параметр задается по умолчанию

TTime &butthead = V;

// Ссылка на объект

При создании каждого объекта выделяется память, достаточная для хранения всех его полей, и автоматически вызывается конструктор, выполняющий их ини­циализацию. Методы класса не тиражируются. При выходе объекта из области действия он уничтожается, при этом автоматически вызывается деструктор.

Дocmyn к элементам объекта аналогичен доступу к полям структуры. Для этого используются операция . (точка) при обращении к элементу через имя объекта и операция -> при обращении через указатель, например:

int n = V.get();

stado[5].draw;

cout « beavis->get();

Обратиться таким образом можно только к элементам со спецификатором publiс. Получить или изменить значения элементов со спецификатором private можно только через обращение к соответствующим методам.

Можно создать константный объект, значения полей которого изменять запре­щается. К нему должны применяться только константные методы:

class monstr{

int get_h()const {return h:}

}:

constmonstr D(0,0);

// Константный объект

cout « D.get_h():

Константный метод:

□ объявляется с ключевым словом const после списка параметров;

□ не может изменять значения полей класса;

□ может вызывать только константные методы;

□ может вызываться для любых (не только константных) объектов.

Рекомендуется описывать как константные те методы, которые предназначены для получения значений полей.

 

Указатель this

Каждый объект содержит свой экземпляр полей класса.

Методы класса находят­ся в памяти в единственном экземпляре и используются всеми объектами совме­стно, поэтому необходимо обеспечить работу методов с полями именно того объ­екта, для которого они были вызваны. Это обеспечивается передачей в функцию скрытого параметра this, в котором хранится константный указатель на вызвав­ший функцию объект.

Указатель this неявно используется внутри метода для ссылок на элементы объекта.

В явном виде этот указатель применяется в основ­ном для возвращения из метода указателя (return this;) или ссылки (return *this;) на вызвавший объект.

Для иллюстрации использования указателя this добавим в приведенный выше класс monstr новый метод, возвращающий ссылку на наиболее здорового (поле health) из двух монстров, один из которых вызывает метод, а другой передается ему в качестве параметра (метод нужно поместить в секцию public описания класса):

Monstr & thebest(monstr &M){

1f( health > М.health) return *this; return M;

... monstr V(50), Super(200);

// Новый объект Best инициализируется значениями полей Super:

monstr Best = V.the_best(Super);

Указатель this можно также применять для идентификации поля класса в том случае, когда его имя совпадает с именем формального параметра метода.

Другой способ идентификации поля использует операцию доступа к области видимости:

void cur(int h,int am){

this -> h += h;

// Использование this

monstr:: am += am;

// Использование операции ::

Конструкторы

Конструктор предназначен для инициализации объекта и вызывается автомати­чески при его создании.

основные свойства конструкторов.

□ Конструктор не возвращает значение, даже типа void.

□ Нельзя получить указа­тель на конструктор.

□ Класс может иметь несколько конструкторов с разными параметрами для раз­ных видов инициализации (при этом используется механизм перегрузки).

□ Конструктор, вызываемый без параметров, называется конструктором по
умолчанию.

Параметры конструктора могут иметь любой тип, кроме этого же класса.
Можно задавать значения параметров по умолчанию. Их может содержать
только один из конструкторов.

□ Если программист не указал ни одного конструктора, компилятор создает его
автоматически. Такой конструктор вызывает конструкторы по умолчанию для полей класса и конструкторы по умолчанию базовых классов. В случае, когда класс содержит константы или ссылки, при попытке создания объекта класса будет выдана ошибка, по­скольку их необходимо инициализировать конкретными значениями, а кон­структор по умолчанию этого делать не умеет.

Конструкторы не наследуются.

□ Конструкторы нельзя описывать с модификаторами const, virtual и static.

□ Конструкторы глобальных объектов вызываются до вызова функции main
Локальные объекты создаются, как только становится активной область их действия. Конструктор запускается и при создании временного объекта (на­ пример, при передаче объекта из функции).

□ Конструктор вызывается, если в программе встретилась какая-либо из син­таксических конструкций:

имя_класса имя_объекта [(список параметров)];

// Список параметров не должен быть пустым

имя_класса (список параметров);

//созд. Объект без имени

Имя_класса имя_объекта=выр-ние;

//создается объект без имени и копируется

 

СТАТИЧЕСКИЕ ЭЛЕМЕНТЫ КЛАССА

 

Статические поля

Статические поля применяются для хранения данных, общих для всех объектов класса, например, количества объектов или ссылки на разделяемый всеми объек­тами ресурс. Эти поля существуют для всех объектов класса в единственном эк­земпляре, то есть не дублируются.

особенности статических полей.

□ Память под статическое поле выделяется один раз при его инициализации независимо от числа созданных объектов (и даже при их отсутствии) и ини­циализируется с помощью операции доступа к области действия, а не опера­ции выбора (определение должно быть записано вне функций):

class A{ public:

static int count;

// Объявление в классе

int A::count;

// Определение в глобальной области

// По умолчанию инициализируется нулем

int Account = 10;

// Пример инициализации произвольным значением

□ Статические поля доступны как через имя класса, так и через имя объекта:

А *а, b;

cout « Account « a->count « b.count;

// Будет выведено одно и то же

На статические поля распространяется действие спецификаторов доступа,
поэтому статические поля, описанные как
private, нельзя изменить с помо­щью операции доступа к области действия, как описано выше. Это можно
сделать только с помощью статических методов
.

Память, занимаемая статическим полем, не учитывается при определении размера объекта с помощью операции sizeof.

Статические методы

Статические методы предназначены для обращения к статическим полям класса. Они могут обращаться непосредственно только к статическим полям и вызывать только другие статические методы класса, потому что им не передается скрытый указатель this.Обращение к статическим методам производится так же, как к статическим полям — либо через имя класса, либо, если хотя бы один объект класса уже создан, через имя объекта.

class A{

staticint count;

// Поле count - скрытое public:

staticvoid inc_count(){ count++: }

А::int count; // Определение в глобальной области void f(){

А а;

// a.count++ - нельзя, поле count скрытое

// Изменение поля с помощью статического метода:

a.inc_count(); // или A::inc_count();

 

Статические методы не могут быть константными (const) и виртуальными (virtual).

 







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.