fp2 = space; // получаем адрес функции space(int, char)

 fp1(22); // Выводим 22 пробела (этот вызов аналогичен вызову (* fp1) (22)) .

 cout << "|\n";

 fp2(30, 'х'); // Выводим 30 символов "х" (этот вызов аналогичен вызову (*fp2) (30, 'x').

 cout << "|\n";

 return 0;

}

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

            I

ХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХ I

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

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

Статические члены класса

Один статический член класса разделяется всеми объектами класса.

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

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

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

#include

using namespace std;

class ShareVar {

  static int num;

 public:

  void setnum(int i) { num = i; };

  void shownum() { cout << num << " "; }

};

int ShareVar::num; // определяем static-член num

int main()

{

 ShareVar a, b;

 a.shownum(); // выводится 0

 b.shownum(); // выводится 0

 a.setnum(10); // устанавливаем static-член num равным 10

 a.shownum(); // выводится 10

 b.shownum(); // также выводится 10

 return 0;

}

Обратите внимание на то, что статический целочисленный член num объявлен и в классе ShareVar, и определен в качестве глобальной переменной. Как было заявлено выше, необходимость такого двойного объявления вызвана тем, что при объявлении члена num в классе ShareVar память для него не выделяется. C++ инициализирует переменную num значением 0, поскольку никакой другой инициализации в программе нет. Поэтому в результате двух первых вызовов функции shownum() для объектов а и b отображается значение 0. Затем объект а устанавливает член num равным 10, после чего объекты а и b снова выводят на экран его значение с помощью функции shownum(). Но так как существует только одна копия переменной num, разделяемая объектами а и b, значение 10 будет выведено при вызове функции shownum() для обоих объектов.

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

Если static-переменная является открытой (т.е. public-переменной), к ней можно обращаться напрямую через имя ее класса, без ссылки на какой-либо конкретный объект. (Безусловно, обращаться можно также и через имя объекта.) Рассмотрим, например, эту версию класса ShareVar.

class ShareVar {

 public:

  static int num;

  void setnum(int i) { num = i; };

  void shownum() { cout << num << " "; }

};

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

Перейти на страницу:

Все книги серии Изучайте C++ с профессионалами

Похожие книги