ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4296
Скачиваний: 28
Глава 14. Классы
191
Статические данные-члены класса только объявляются внутри
класса. Они должны быть определены, а в случае констант и
инициализированы вне класса. Пример работы со статическими
данными-членами класса приведен в листинге 14.10.
Листинг 14.10. Работа со статическими данными-членами класса
#include <iostream>
using namespace std;
struct Demo
{
static int n;
static const int m;
};
int Demo::n;
const int Demo::m = 10;
int main()
{
Demo::n = 20;
cout << Demo::n << ' ' << Demo::m << endl; // 20 10
return 0;
}
Можно определять указатели на статические данные-члены клас-
са, если они расположены в разделе
public
. Например:
int* p = &Demo::n;
Статические функции-члены класса имеют доступ только к ста-
тическим данным-членам класса. Для того чтобы эти функции
имели доступ к нестатическим членам класса, они должны
получить адрес объекта класса как параметр. Пример работы
со статическими функциями-членами класса приведен в
листинге 14.11.
Листинг 14.11. Работа со статическими функциями-членами класса
#include <iostream>
using namespace std;
Часть II. Язык программирования С++
192
class Demo
{
int n;
static int m;
public:
Demo() { n = 10; ++m; }
static int getN(Demo& d) { return d.n; }
static int getM() { return m; }
int getSum() { return n + m; }
};
int Demo::m;
int main()
{
Demo d;
cout << d.getN(d) << endl; // 10
cout << d.getM() << endl; // 1
cout << d.getSum() << endl; // 11
return 0;
}
Статические функции-члены класса ведут себя аналогично гло-
бальным функциям. Например, указателю на функцию можно
присвоить адрес статической функции-члена класса.
int (*f)(void) = Demo::getM;
14.11. Указатели
на нестатические члены класса
При определении указателей на нестатические члены класса сле-
дует учитывать как тип члена класса, так и тип самого класса.
Определение указателя на нестатический атрибут класса имеет
следующий вид:
тип_атрибута имя_класса::* имя_указателя
В свою очередь определение указателя на нестатический метод
класса имеет следующий вид:
тип (имя_класса::* имя_указателя)(список_параметров)
Глава 14. Классы
193
Для доступа к нестатическим членам класса через указатели ис-
пользуются операторы:
.*
— для объектов или ссылок на объекты;
->*
— для указателей на объекты.
Эти операторы имеют ассоциативность слева направо, а их при-
оритет ниже приоритета унарных арифметических операторов, но
выше приоритета бинарных арифметических операторов.
В листинге 14.12 приведен пример использования операторов
доступа к нестатическим членам класса через указатели.
Листинг 14.12. Доступ к нестатическим членам класса
через указатели
#include <iostream>
using namespace std;
struct Demo
{
int n;
int Count() { return n; };
};
int main()
{
Demo d;
Demo* dp = &d;
int Demo::*ip; // указатель на атрибут
int (Demo::*fp)(); // указатель на метод
// инициализация указателей
ip = &Demo::n;
fp = Demo::Count;
// доступ к атрибуту через объект
d.*ip = 10;
cout << d.*ip << endl; // печатает 10
// доступ к атрибуту через указатель на объект
dp->*ip = 20;
cout << dp->*ip << endl; // печатает 20
Часть II. Язык программирования С++
194
d.*ip += 10;
// доступ к методу через объект
cout << (d.*fp)() << endl; // печатает 30
// доступ к методу через указатель на объект
cout << (dp->*fp)() << endl; // печатает 30
return 0;
}
14.12. Вложенные классы
Класс, объявленный внутри другого класса, называется
вло-
женным
классом. Класс, в котором объявлен вложенный класс,
будем называть
объемлющим
классом.
Функции-члены объемлющего класса не имеют прав доступа к
закрытым членам своего вложенного класса. Также и функции-
члены вложенного класса не имеют прав доступа к закрытым
членам класса, внутри которого он объявлен. Чтобы предоставить
такие права вложенному или объемлющему классу, нужно объ-
явить такой класс другом соответственно объемлющего или вло-
женного класса.
В листинге 14.13 приведен пример объявления вложенного
класса.
Листинг 14.13. Пример объявления вложенного класса
#include <iostream>
using namespace std;
class Outer
{
class Inner
{
int n;
public:
Inner() { n = 0; }
int count() { return ++n; }
};
Inner n;
Глава 14. Классы
195
public:
int count() { return n.count(); }
};
int main()
{
Outer n;
cout << n.count() << endl; // печатает 1
return 0;
}
Для того чтобы объект, который имеет тип вложенного класса,
можно было объявить вне объемлющего класса, вложенный класс
должен быть объявлен в разделе открытых членов объемлющего
класса. При этом, т. к. определение объемлющего класса вводит
область видимости, при ссылке на имя вложенного класса вне
этой области видимости оно должно квалифицироваться именем
объемлющего класса.
В листинге 14.14 приведен пример объявления объекта, который
имеет тип вложенного класса.
Листинг 14.14. Объявление объекта типа вложенного класса
#include <iostream>
using namespace std;
class Outer
{
public:
class Inner
{
int n;
public:
Inner() { n = 0; }
int count() { return ++n; }
};
private:
Inner n;