
- •5.Препроцессор. Директивы препроцессора.
- •7.Работа с файлами. Текстовый и двоичный режим.
- •8.Указатели. Адресная арифметика.
- •10.Перечислимый тип. Структуры. Объединения.
- •11.Поразрядные операции.
- •13.Спецификаторы класса памяти.
- •14.Пространства имён.
- •15.Компоновка. Правило одного определения.
- •16.Понятие класса.
- •17.Функции-члены класса. Указатель this.
- •18.Конструкторы. Деструкторы.
- •19.Преобразования объектов класса.
- •20.Доступ к членам класса.
- •21.Статические члены класса.
- •22.Друзья класса.
- •23.Совместное использование.
- •24.Перегрузка операций.
- •25.Шаблоны.
- •26.Обработка исключительных ситуаций.
- •27.Производные классы.
- •28.Виртуальные функции. Абстрактные классы.
- •29.Указатели на члены класса.
- •30.Множественное наследование.
- •31.Структура dll-библиотеки.
- •32.Статическое и динамическое подключение dll-библиотек.
- •34.Регистры процессора.
- •35.Использование стека. Команды работы со стеком в языке ассемблера.
- •36.Арифметические команды в языке ассемблера.
- •37.Команды сравнения и перехода в языке ассемблера.
- •38.Команды работы с битами в языке ассемблера.
- •39.Процедуры в языке ассемблера. Передача параметров в процедуру.
- •40.Процедуры в языке ассемблера. Возврат результата. Локальные данные.
20.Доступ к членам класса.
Управление доступом применяется единообразно к функциям-членам класса и данным-членам класса.
Член класса может быть:
приватным (private) – это значит, что его имя может употребляться лишь внутри функций-членов класса и друзей класса, в котором этот член класса объявлен;
защищённым (protected) – это значит, что его имя может употребляться лишь внутри функций-членов класса, друзей этого класса и производных от него классов;
публичным (public) – это значит, что его имя может употребляться внутри любой функции (а также и вне функций в инициализаторах).
Модификаторы доступа можно использовать несколько раз в одном и том же объявлении класса.
Механизмы управления доступом в C++ обеспечивают защиту от случайного, а не от преднамеренногодоступа. Однако это относится к проблемам дисциплины программирования, а не к проблемам языка.
Члены класса без спецификатора доступа по умолчанию являются приватными. Члены структур иобъединений по умолчанию являются публичными.
21.Статические члены класса.
При объявлении класса данные-члены и функции-члены класса можно объявлять статическими с помощью ключевого слова static. Существует лишь один экземпляр статических данных-членов класса,разделяемый всеми объектами этого класса в программе. Статический член является не частью объектов класса, а отдельным объектом. Статический член класса будет существовать, даже если не создано ни одного объекта класса.
Объявление статических данных-членов внутри определения класса не является его определением. Определение должно быть дано где-нибудь ещё.
Статический член mem класса cl можно обозначать как cl::mem, т.е. независимо от объекта. На него можно также ссылаться при помощи операций доступа к членам класса . и ->. При обращении к статическому члену класса через операцию доступа к членам класса выражение слева от этой операции не вычисляется.Функция-член класса также может быть статической. Такая функция не получает указатель this и может ссылаться на нестатические члены класса только посредством операций доступа к членам класса (. и ->).
static void SetSize(int x, int y);
static int GetCount(); // Статические функции-члены класса
Статическая функция-член класса не может быть виртуальной. Не могут существовать одновременно статическая и нестатическая функция-член класса с одинаковым именем и одинаковым набором параметров.Статические члены глобального класса имеют внешнее связывание, т.е. могут быть доступны из других файлов программы. Локальные (т.е. объявленные внутри некоторой функции) классы не могут иметь статических членов.
Статические члены класса подчиняются обычным правилам доступа к членам класса.Константные статические члены класса могут быть инициализированы внутри определения класса. class BitSet
{ private: typedef _int64 elem;
static const int cBits = sizeof(elem) * 8;
static const int size = 256 / cBits;
elem set[size]; ... };
22.Друзья класса.
Обычное объявление функции-члена класса гарантирует три логически разные вещи:
функция имеет право доступа к приватным членам класса;
функция находится в области видимости класса;
функция должна вызываться для объекта класса (имеется указатель this).
Объявив функцию статической, мы придаём ей только первые два свойства. Объявив функцию дружественной, мы наделяем её только первым свойством.Друг класса – это функция, которая не является членом этого класса, но которой разрешается использовать его приватные и защищённые члены. Имя друга класса не лежит в области действия этого класса, и друг класса не вызывается при помощи операции доступа к члену класса.
Друг класса, как и его члены, является частью интерфейса класса. Дружба, как и другие права доступа, предоставляются классом, а не захватываются.
Спецификаторы доступа не затрагивают объявлений дружественных функций. «Дружба» не обладает ни наследуемостью, ни транзитивностью.
class X { private: int n; friend void friend_function(X* p, int i); public: void member_function(int i); }; |
// Спецификатор доступа private не работает |
void friend_function(X* p, int i) { p->n = i; } |
// Функция не является членом класса, поэтому X:: не пишем. // Поскольку дружественная функция не является членом класса, она не получает указатель this // и ей необходимо явно передавать объект, с которым она будет работать. |
void X::member_function(int i) { n = i; } |
// Имеется в виду this->n = i |
void f() { X obj; friend_function(&obj, 10); obj.member_function(10); } |
// Функции вызываются по-разному, // но приводят к одному и тому же результату |
Когда дружественной объявляется совместно используемая функция, другом становится лишь функция с заданными типами параметров. Это сделано, чтобы избежать «захвата» прав доступа путём объявления ещё одной совместно используемой функции с новым набором параметров.
Функция-член класса Х может быть дружественной классу Y. class Y
{ friend void X::f(); ... };
Сразу все функции-члены класса Х могут быть объявлены дружественными классу Y: class Y
{ friend class X; ... };
Механизм дружественности важен по двум причинам. Во-первых, функция может быть другом двух классов. Это увеличивает эффективность работы такой функции и упрощает интерфейсы классов.
Во-вторых, дружественная функция допускает применение пользовательских преобразований к своему первому параметру, в то время как функции-члены класса – нет*. Это позволяет программисту выразить требование к первому параметру быть l-значением**, описав соответствующую функцию как член класса, и напротив, выразить отсутствие такого требования, описав такую функцию как дружественную.
class Complex
{ private:
double r, m;
public:
Complex(double r = 0, double m = 0) : r(r), m(m) { }
//operator double () { return r; };
Complex operator =(const Complex& c);
friend Complex operator ++(Complex& c);
friend Complex operator ++(Complex& c, int);
friend Complex operator + (const Complex& c1, const Complex& c2);
Complex operator +=(const Complex& c); }; |
// Функцию operator += лучше реализовывать как функцию-член класса |
Complex Complex::operator =(const Complex& c)
{ if (&c == this) return *this;
r = c.r;
m = c.m;
return *this; }
Complex operator ++(Complex& c)
{ ++c.r; return c; }
Complex operator ++(Complex& c, int)
{ Complex x = c;
c.r++;
return x; }
Complex operator +(const Complex& c1, const Complex& c2)
{ return Complex(c1.r + c2.r, c1.m + c2.m); }
Complex Complex::operator +=(const Complex& c)
{ r += c.r;
m += c.m;
return *this; }
void main() { Complex a(0, 0), b(2, 2), c; double d = 2; c = ++a; c = a++; c = a + ++b; c = a + d; c = 3 + b; c += 4; 2 += c; } |
// Неявные вызовы преобразующего конструктора. // При наличии функции преобразования operator double() возникала бы неоднозначность.
// Ошибка, даже при наличии преобразования из числа типа double к классу Complex, // т.к. 2 не является l-значением |