Листинг 14.2. Доступ к статическим членам без использования объектов



1: // Листинг 14.2. Статические переменные-члены

2:

3: #include <iostream.h>

4:

5: class Cat

6: {

7: public:

8: Cat(int age):itsAge(age) { HowManyCats++; }

9: virtual ~Cat() { HowManyCats--; }

10: virtual int GetAge() { return itsAge; }

11: virtual void SetAge(int age) {itsAge = age;}

12: static int HowManyCats;

13:

14: private:

15: int itsAge;

16:

17: };

18:

19: int Cat::HowManyCats = 0;

20:

21: voidTelepathicFunction();

22:

23: int main()

24: {

25: const int MaxCats = 5; int i;

26: Cat *CatHouse[MaxCats];

27: for (i = 0; i<MaxCats; i++)

28: {

29: CatHouse[i] = new Cat(i);

30: TelepathicFunction();

31: }

32:

33: for ( i = 0; i<MaxCats; i++)

34: {

35: delete CatHouse[i];

36: TelepathicFunction();

37: }

38: return 0;

39: }

40:

41: void TelepathicFunction()

42: {

43: cout << "There are ";

44: cout << Cat::HowManyCats << " cats alive!\n";

45: }

 

Результат:

There are 1 cats alive!

There are 2 cats alive!

There are 3 cats alive!

There are 4 cats alive!

There are 5 cats alive!

There are 4 cats alive!

There are 3 cats alive!

There are 2 cats alive!

There are 1 cats alive!

There are 0 cats alive!

 

Анализ: Листинг 14.2 аналогичен листингу 14.1, однако включает новую функцию TelepahicFunction().Она не создает объект СаГ и даже не использует тегов качестве параметра, однако может получить доступ к переменной-члену HowManyCats. Не лишним будет еще раз напомнить, что эта переменная-член относится не к какому-либо определенному объекту, а ко всему классу в целом. Поэтому если она объявлена как public, то может использоваться любой функцией программы.

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

Листинг 14.3. Доступ к статическим членам с помощью обычных функций-членов

1: //Листинг 14.3. Закрытые статические переменные-члены

2:

3: #include <iostream.h>

4:

5: class Cat

6: {

7: public:

8: Cat(int age):itsAge(age){ HowManyCats++; }

9: virtual ~Cat() { HowManyCats--; }

10: virtual int GetAge() { return itsAge; }

11: virtual void SetAge(int age) { itsAge = age; }

12: virtual int GetHowMany() { return HowManyCats; }

13:

14:

15: private:

16: int itsAge;

17: static int HowManyCats;

18: };

19:

20: int Cat::HowManyCats = 0;

21:

22: int main()

23: {

24: const int MaxCats = 5; int i;

25: Cat *CatHouse[MaxCats];

26: for (i = 0; i<MaxCats; i++)

27: CatHouse[i] = new Cat(i);

28:

29: for (i = 0; i<MaxCats; i++)

30: {

31: cout << "There are ";

32: cout << CatHouse[i]->GetHowMany();

33: cout << " cats left!\n";

34: cout << "Deleting the one which is ";

35: cout << CatHouse[i]->GetAge()+2;

36: cout << " years old\n";

37: delete CatHouse[i];

38: CatHouse[i] = 0;

39: }

40: return 0;

41: }

 

Результат:

There are 5 cats left!

Deleting the one which is 2 years old

There are 4 cats left!

Deleting the one which is 3 years old

There are 3 cats left!

Deleting the one which is 4 years old

There are 2 cats left!

Deleting the one which is 5 years old

There are 1 cats left!

Deleting the one which is 6 years old

 

Анализ: В строке 17 статическая переменная-член HowManyCats объявлена как private. Поэтому теперь доступ к ней закрыт для функций, не являющихся членами класса, например для функции TelepathicFunction из предыдущего листинга.

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

 

Рекомендуется: Применяйте статические переменные-члены для совместного использования данных несколькими объектами класса. Ограничьте доступ к статическим переменным-членам, объявивих как private или protected.

 

Не рекомендуется: Не используйте статические перемен- ные-члены для хранения данных одного объекта. Эти переменные предназначены для обмена данными между объектами.

 

Статические функции-члены

 

Статические функции-члены подобны статическим переменным-членам: они не принадлежат одному объекту, а находятся в области видимости всего класса. Именно поэтому их можно вызывать даже в тех случаях, когда не было создано ни одного объекта класса, как показано в листинге 14.4.

Листинг 14.4. Статические функции-члены

1: // Листинг 14.4. Статические функции-члены

2:

3: #include <iostream.h>

4:

5: class Cat

6: {

7: public:

8: Cat(int age):itsAge(age){ HowManyCats++; }

9: virtual ~Cat() { HowManyCats--; }

10: virtual int GetAge() { return itsAge; }

11: virtual void SetAge(int age) { itsAge = age; }

12: static int GetHowMany() { return HowManyCats; }

13: private:

14: int itsAge;

15: static int HowManyCats;

16: };

17:

18: int Cat::HowManyCats = 0;

19:

20: void TelepathicFunction();

21:

22: int main()

23: {

24: const int MaxCats = 5;

25: Cat *CatHouse[MaxCats]; int i;

26: for (i = 0; i<MaxCats; i++)

27: {

28: CatHouse[i] = new Cat(i);

29: TelepathicFunction();

30: }

31:

32: for ( i = 0; i<MaxCats; i++),

33: {

34: delete CatHouse[i];

35: TelepathicFunction();

36: }

37: return 0;

38: }

39:

40: void TelepathicFunction()

41: {

42: cout << "There are " << Cat::GetHowMany() << " cats alive!\n";

43: }

 

Результат:

There are 1 cats alive!

There are 2 cats alive!

There are 3 cats alive!

There are 4 cats alive!

There are 5 cats alive!

There are 4 cats alive!

There are 3 cats alive!

There are 2 cats alive!

There are 1 cats alive!

There are 0 cats alive!

 

Анализ: В строке 15 в объявлении класса Cat создается закрытая статическая переменная-член HowManyCats. В строке 12 объявляется открытая статическая функция-член GetHowMany().

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

 

Примечание: Статические функции-члены не содержат указателя this. Поэтому они не могут объявляться со спецификатором const. Кроме того, поскольку функции-члены получают доступ к переменным-членам с помощью указателя this, статические функции-члены не могут использовать обычные нестатические переменные-члены!

 

Статические функции-члены

Доступ к статическим функциям-членам можно получить, либо вызывая их из объектов класса как обычные функции-члены, либо вызывая их без объектов, явно указав в этом случае имя класса. Пример:

class Cat

{

public:

static int GetHowMany() { return HowManyCats; }

private:

static int HowManyCats;

}

int Cat::HowManyCats = 0;

int main()

{

int howMany;

Cat theCat; // определение обьекта

howMany = theCat.GetHowMany(); // доступ через объект

howMany = Cat::GetHowMany(); // доступ без объекта

}

 

Указатели на функции

 

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

Единственная важная деталь для определения указателя на функцию — знание типа объекта, на который ссылается указатель. Указатель типа int обязательно связан с целочисленной переменной. Аналогичным образом указатель на функцию может вызывать только функции с заданными сигнатурой и типом возврата.

В объявлении

long (*funoPtr) (int);

создается указатель на функцию funcPtr (обратите внимание на символ * перед именем указателя), которая принимает целочисленный параметр и возвращает значение типа long. Круглые скобки вокруг (*funcPtr) обязательны, поскольку скобки вокруг (int) имеют больший приоритет по сравнению с оператором косвенного обращения (*). Если убрать первые скобки, то это выражение будет объявлять функцию funcPtr, принимающую целочисленный параметр и возвращающую указатель на значение типа long. (Вспомните, что все пробелы в C++ игнорируются,) Рассмотрим два следующих объявления:

long * Function (int); long (*funcPtr) (int);

В первой строке Function() — это функция, принимающая целочисленный параметр и возвращающая указатель на переменную типа long. Во втором примере funcPtr — это указатель на функцию, принимающую целочисленный параметр и возвращающую переменную типа long.

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


Дата добавления: 2019-02-12; просмотров: 224; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!