![](/user_photo/2706_HbeT2.jpg)
- •Содержание
- •ВВЕДЕНИЕ
- •1.ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД
- •2. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
- •2.1. Абстрактные типы данных
- •2.2. Базовые принципы объектно-ориентированного программирования
- •2.3. Основные достоинства языка С++
- •2.4. Особенности языка С++
- •2.4.1. Ключевые слова
- •2.4.2. Константы и переменные
- •2.4.3. Операции
- •2.4.4. Типы данных
- •2.4.5. Передача аргументов функции по умолчанию
- •2.5.1. Объект cin
- •2.5.2. Объект cout
- •2.5.3. Манипуляторы
- •3.1. Объекты
- •3.2. Понятие класса
- •3.3. Конструктор копирования
- •3.4. Конструктор explicit
- •3.5. Указатель this
- •3.6. Встроенные функции (спецификатор inline)
- •3.7. Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •3.8. Вложенные классы
- •3.9. Static-члены (данные) класса
- •3.10. Компоненты-функции static и const
- •3.11. Proxi-классы
- •3.12. Ссылки
- •3.12.1. Параметры ссылки
- •3.12.2. Независимые ссылки
- •3.13. Пространства имен
- •3.13.3. Ключевое слово using как объявление
- •3.13.4. Псевдоним пространства имен
- •3.14. Практические приемы ограничения числа объектов класса
- •4. НАСЛЕДОВАНИЕ
- •4.1.1. Конструкторы и деструкторы при наследовании
- •4.2. Виртуальные функции
- •4.3. Абстрактные классы
- •4.4. Виртуальные деструкторы
- •4.6. Виртуальное наследование
- •5.2. Перегрузка операторов
- •5.2.2. Перегрузка унарного оператора
- •5.2.3. Дружественная функция operator
- •5.2.4. Особенности перегрузки операции =
- •5.2.5. Перегрузка оператора []
- •5.2.6. Перегрузка оператора ()
- •5.2.7. Перегрузка оператора ->
- •5.2.8. Перегрузка операторов new и delete
- •5.3. Преобразование типа
- •5.3.1. Явные преобразования типов
- •6. ШАБЛОНЫ
- •6.1. Параметризированные классы
- •6.2. Передача в шаблон класса дополнительных параметров
- •6.3. Шаблоны функций
- •6.4. Совместное использование шаблонов и наследования
- •6.5. Шаблоны класса и friend-функции
- •6.6. Некоторые примеры использования шаблона класса
- •6.6.1. Реализация smart-указателя
- •6.6.2. Задание значений параметров класса по умолчанию
- •7.2. Состояние потока
- •7.3. Строковые потоки
- •7.4. Организация работы с файлами
- •7.5. Организация файла последовательного доступа
- •7.6. Создание файла произвольного доступа
- •7.7. Основные функции классов ios, istream, ostream
- •8. ИСКЛЮЧЕНИЯ В С++
- •8.2. Перенаправление исключительных ситуаций
- •8.3. Исключительная ситуация, генерируемая оператором new
- •8.6. Спецификации исключительных ситуаций
- •8.7. Задание собственного неожиданного обработчика
- •9. СТАНДАРТНАЯ БИБЛИОТЕКА ШАБЛОНОВ (STL)
- •9.3. Категории итераторов
- •9.4. Операции с итераторами
- •9.5. Контейнеры последовательностей
- •9.5.2. Контейнер последовательностей list
- •9.5.3. Контейнер последовательностей deque
- •9.6. Ассоциативные контейнеры
- •9.6.1. Ассоциативный контейнер multiset
- •9.6.2. Ассоциативный контейнер set
- •9.6.3. Ассоциативный контейнер multimap
- •9.7.1. Адаптер stack
- •9.7.2. Адаптер queue
- •9.7.3. Адаптер priority_queue
- •9.8. Алгоритмы
- •9.8.1. Алгоритмы сортировки sort, partial_sort, sort_heap
- •9.8.2. Алгоритмы поиска find, find_if, find_end, binary_search
- •9.8.3. Алгоритмы fill, fill_n, generate и generate_n
- •9.8.4. Алгоритмы equal, mismatch и lexicographical_compare
- •9.8.6. Алгоритмы работы с множествами
- •9.8.7. Алгоритмы swap, iter_swap и swap_ranges
- •9.8.8. Алгоритмы copy, copy_backward, merge, unique и reverse
- •10. ПРИМЕРЫ РЕАЛИЗАЦИИ КОНТЕЙНЕРНЫХ КЛАССОВ
- •10.1. Связанные списки
- •10.1.1. Реализация односвязного списка
- •10.2. Реализация бинарного дерева
- •11. ПРОГРАММИРОВАНИЕ ДЛЯ WINDOWS
- •11.1. Система, управляемая сообщениями
- •11.2. Управление графическим выводом
- •11.3. Контекст устройства
- •11.3.1. Экран
- •11.3.2. Принтер
- •11.3.3. Объект в памяти
- •11.3.4. Информационный контекст
- •11.4. Архитектура, управляемая событиями
- •11.5. Исходный текст программы
- •11.7. Некоторые новые типы данных
- •11.8. Венгерская нотация
- •11.9. Точка входа программы
- •11.11. Создание окна
- •11.12. Цикл обработки сообщений
- •11.13. Оконная процедура
- •11.14. Обработка сообщений
- •11.15. Обработка сообщений функцией DefWindowProc
- •11.16. Синхронные и асинхронные сообщения
- •11.17. Еще один метод получения описателя контекста устройства
- •11.19. Полосы прокрутки
- •Литература
}
int main()
{ NAME::n1=3;
|
// n1=4; |
error |
'n1' надо указывать полностью NAME::n1 |
|||
|
// n2=5; |
error |
'n2' : undeclared identifier |
|
|
|
|
// int n2; |
следующая строка приводит к ошибке |
|
|||
|
using NAME::n2; |
// далее n2 доступно |
|
|
||
|
n2=6; |
|
|
|
|
|
|
cout <<NAME::n1<<" "<< n2 << endl; // результат |
3 6 |
Р |
|||
|
{ NAME::n1=7; |
|
|
|||
|
n2=8; |
|
|
|
|
|
|
cout <<NAME::n1<<" "<< n2 << endl;// результат |
7 8 |
||||
|
} |
|
|
|
|
|
|
|
|
|
И |
||
} |
return 0; |
|
|
|
||
|
|
|
|
|||
В результате выполнения программы получим:У |
|
|||||
3 |
6 |
|
|
Г |
|
|
7 |
8 |
|
|
|
|
Объявление using добавляет определенноеаБимя в текущую область дейст-
вия. В примере к переменной n2 можно обр щаться без указания принадлежно- сти классу, а для n1 необходимо полное имя. Объявление using обеспечивает более подробное управление и нами, переносимыми в пространство имен. Это
|
|
|
|
т |
|
||
и есть ее основное отличие от дирктивы, которая переносит все имена про- |
|||||||
странства имен. |
про |
ме |
|
||||
|
Внесение в локальную область (блок) имени, для которого выполнено яв- |
||||||
ное объявление (и на б р ), является серьезной ошибкой. |
|||||||
|
|
и |
|
|
|
||
|
3.13.4. Псевд н м прос ранства имен |
||||||
|
Псевдон м |
странства имен существует для того, чтобы назначить дру- |
|||||
|
|
л |
|
|
|
|
|
гое имя именованному пространству имен. |
|||||||
|
б} |
|
|
|
// пространство имен |
||
|
namespace spisok_name_peremen |
||||||
|
{ int n1=1; |
|
|
|
|
||
и |
|
|
|
|
|
||
Б |
. . . |
|
|
|
|
||
NAME = spisok_name_peremen; |
// псевдоним пространства имен |
||||||
|
Пространству имен spisok_name_peremen назначается псевдоним NAME. В этом случае результат выполнения инструкций:
cout <<NAME::n1<< endl;
cout<< spisok_name_peremen::n1<<endl;
будет одинаков.
3.14. Практические приемы ограничения числа объектов класса
Иногда для эффективной работы желательно ограничивать число объек-
61
тов. Пусть, например, разрабатывается класс для принтера. При этом в системе необходимо при множестве клиентов (заданий, объектов класса PrntJob) иметь только один объект (принтер, объект класса Printer). Это может быть достигнуто инкапсуляцией объекта «принтер» в одну из функций. Все конструкторы класса Printer должны быть закрытые и могут быть вызваны только из открытых мето- дов класса Printer или методов, дружественных этому классу. Кроме того, соз- даваемый объект является статическим, что исключает возможность его по- вторного создания.
#include <iostream> |
|
|
|
|
|
|
|
|
|
|
Р |
|||
|
|
|
|
|
|
|
|
|
|
|
||||
using std::cout; |
|
|
|
|
|
|
|
|
|
|
И |
|||
using std::endl; |
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|||
#include <string> |
|
|
|
|
|
|
|
|
|
|
|
|
||
using std::string; |
|
|
|
|
|
|
|
|
|
|
|
|
||
class PrntJob; |
|
|
// предварительное объявление |
|
|
|
||||||||
class Printer |
|
|
|
// класс «принтер» |
|
Г |
|
|
||||||
|
|
|
Б |
У |
|
|||||||||
{ Printer(){} |
|
|
|
|
|
|
|
|
|
|||||
|
Printer(const Printer& obj){}; |
|
|
|
|
|
|
|
|
|||||
public: |
|
|
|
|
|
|
|
да |
|
|
|
|
||
|
void Job(PrntJob&); |
|
// |
функция выво з д ния |
|
|
|
|||||||
|
friend Printer& Print(); |
// |
|
|
к |
|
|
|
|
|
||||
|
функция возвр щ ет ссылку |
|
|
|
||||||||||
}; |
|
|
|
// на объ т «принтер» |
|
|
|
|
||||||
class PrntJob |
|
|
// |
класс «задание» |
|
|
|
|
|
|||||
{ string str; |
|
|
|
|
т |
|
|
|
|
|
|
|
||
public: |
|
|
о |
е |
|
|
|
|
|
|
||||
}; |
|
|
|
|
|
|
|
|
|
|
||||
|
void get(const string str) |
// инициализация объекта «задание» |
|
|||||||||||
|
{this->str=str;} |
и |
// в зврат ссылки на текущее задание |
|
||||||||||
|
string& put(){return str;} |
|
||||||||||||
|
|
л |
|
|
|
|
|
|
|
|
|
|
|
|
void Printer::Job(PrntJob& obj) |
|
|
|
|
|
|
|
|
||||||
{cout<<obj.put()<<endl; |
|
|
|
|
|
|
|
|
|
|||||
} |
и |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Б |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Printer& Print()б |
|
|
// статический объект «принтер» |
|
|
|
||||||||
{ static Printer pr; |
|
|
|
|
|
|||||||||
} |
return pr; |
|
|
|
// возврат ссылки на объект «принтер» |
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ PrntJob ob1,ob2; |
|
|
|
|
|
|
|
|
|
|
|
|||
|
ob1.get("задание 1"); |
|
|
|
|
|
|
|
|
|
|
|||
|
ob2.get("задание 2"); |
|
|
|
|
|
|
|
|
|
|
|||
|
// cout<<&Print()<<endl; |
// выводится адрес объекта «принтер» |
|
|||||||||||
|
Print().Job(ob1); |
|
|
|
|
|
|
|
|
|
|
|
|
62
// cout<<&Print()<<endl; Print().Job(ob2);
}
В результате работы программы получим: задание 1 задание 2
Если при этом выводить адреса объекта «принтер», создаваемого для вы- вода первого и второго задания, то получим одинаковые адреса. Следовательно,
можно утверждать, что в функции Print создается единственный объект для вы- |
|||||||||||||
вода всех заданий. |
|
|
|
|
|
|
|
|
Р |
||||
|
|
|
|
|
|
|
|
|
|||||
|
Можно поступить |
иначе, |
сделав |
функцию |
Print статическим членом- |
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
И |
|
функцией класса Printer. Это также исключает необходимость использования |
|||||||||||||
friend-механизма для функции Print. |
|
|
|
|
|||||||||
|
class PrntJob; |
|
|
// предварительное объявление |
|
||||||||
|
class Printer |
|
|
// класс «принтер» |
У |
|
|||||||
|
{ Printer(){} |
|
|
|
|
|
|
Г |
|
||||
|
|
Printer(const Printer& obj){}; |
|
|
|||||||||
|
|
public: |
|
|
|
|
|
|
|
Б |
|
|
|
|
|
void Job(PrntJob&); |
|
|
|
а |
|
|
|||||
|
|
|
// функция вывода задания |
|
|||||||||
|
|
static Printer& Print(); |
|
|
к |
|
|
|
|||||
|
|
|
// созд ние ст тического объекта «принтер» |
||||||||||
|
|
. . . |
|
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
т |
|
|
|
|
|
|
|||
|
class PrntJob |
// |
класс «задание» |
|
|
||||||||
|
{ . . . |
о |
е |
|
|
|
|
||||||
|
}; |
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
||
|
void Printer::Job(PrntJob& obj) |
|
|
|
|
||||||||
|
{cout<<obj.put()<<endl; |
|
|
|
|
|
|
|
|||||
|
} |
|
л |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
б} |
|
|
|
|
|
|
|
|
|
|
||
|
Printer&иPrinter::Print() |
|
|
|
|
|
|
|
|||||
|
{ static Printer pr; |
|
|
// статический объект «принтер» |
|
||||||||
и |
|
|
|
|
// возврат ссылки на объект «принтер» |
||||||||
Б |
|
return pr; |
|
|
|
||||||||
int main() |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
{ PrntJob ob1,ob2; ob1.get("задание 1"); ob2.get("задание 2");
Printer::Print().Job(ob1); // вызов объекта принтер для объекта задание
Printer::Print().Job(ob2);
}
Вопросы и упражнения для закрепления материала
63
1.В чем разница между struct, class и union?
2.Что такое указатель this? Приведите пример использования этого указателя.
3.Какова основная форма конструктора копирования и когда он вы- зывается?
4.Откомпилируется ли следующая программа, если да, то что она выве- дет на экран?
#include <iostream> using namespace std; void f()
{ class A |
|
|
|
|
|
|
|
Р |
||
|
{ public: |
|
|
|
|
|
|
|
||
|
void g() {cout << "A::g"<<endl;} |
|
У |
|||||||
|
}; |
|
|
|
|
|
|
Г |
И |
|
|
A a; |
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
||
} |
a.g(); |
|
|
|
|
|
Б |
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
int main() |
|
|
|
|
|
программы, если да, то |
||||
5. Возникнут ли ошибки при компиляциианнойд |
||||||||||
{ |
f(); |
|
|
|
|
|
|
|
|
|
} |
return 0; |
|
|
|
|
|
|
|
|
|
почему, если нет, то что выведет программакна э ран: |
|
|
|
|||||||
#include <iostream> |
|
|
е |
|
|
|
||||
using namespace std; |
|
|
|
|
|
|||||
|
т |
|
|
|
||||||
int I1=1; |
|
|
|
|
|
|
|
|||
int I2=2; |
|
|
|
|
|
|
|
|||
class A |
|
|
|
о |
|
|
|
|
||
{ |
const int& i; |
и |
|
|
|
|
|
|||
public: |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
||
|
A():i(I1){}; |
|
|
|
|
|
|
|
||
|
|
|
л |
|
|
|
|
|
|
|
|
friend void f(A&); |
|
|
|
|
|
|
|||
}; |
|
б |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f(A& a) |
|
|
|
|
|
|
|
|
||
|
и |
|
|
|
|
|
|
|
|
|
{ a.i = I2;} |
|
|
|
|
|
|
|
|
||
Бint main() |
|
|
|
|
|
|
|
|
{ A a; f(a);
cout<<I1<<I2; return 0;
}
64