|
Программирование >> Унарные и бинарные операторы
Следующая инструкция создает новый тип ml - массив из NC целых переменных: typedef int ml[NC]: Обьявление ml m2 2[NR], очевидно, создает массив из NR массивов ml, то есть массив массивов, о котором мы знаем, что он занимает непрерывный участок памяти и к отдс;1ьным элементам которого можно обратиться как к m2 2[i][j]. Но если ири1нлсать слева ключевое слово typedef, как показано ниже, то массив массивов исчезнет и вазникнет новый тип т2 2: typedef ml m2 2[NR]: Если объявить объект р типа т2 2: т2 2 р, то теперь р - это массив v\A NR массивов, в каждом из которых по NC переменных типа int. И к этому .массиву можно обра-П1аться обычным обра-зом, как показано в листинге 13.6. Задача 13.3. Путем последовательного применения typedef создайте указатель на функцию, возвращающую указатель на char. объявления объекта, мы уничтожаем сам объект, делая его именем нового типа. Пусть, например, в программе объявлена переменная: unsigned int ui: Это, как мы знаем, беззнаковая целочисленная пе-11еменная ui, занимающая определенное место в памяти. Если приггисать слева typedef, то сама переменная пропадет и возникнет новый тип ui - беззнаковая целочисленная переменная: typedef unsigned int ui: После этого показанное ниже объявление будет означать, что создается переменная р типа ui: ui р: Тип ui по своей сути не новый, новое у него лишь название, ставшее гораздо короче. Чтобы вы не относились к объекту typedef легкомысленно и пе считали его простеньким средством украшения программ, рассмотрим еще один более сложный пример, когда ключевое слово typedef применяется поэтапно, и в результате создается довольно за.мыслона-тый тип (листинг 13.6). Листинг 13.6 #include <iostream> using namespace std: #define NR 40 #define NC 30 int main(){ typedef int ml[NC]: typedef ml m2 2[NR]: m2 2 p: forCint i=0:i<NR:i++) for(int j=0:j<NC:j++) p[i][j]=i*j: cout p[35][l] endl; return 0: Заключение Учитель истории упрекал ученика за то, что тот не знает ни одной даты. - Напротив, -отвечал ученик, -язпаю все даты и могу их прямо сейчас перечислить. Я только не знаю, что в этп даты происходили. Анекдот Перефразируя гениальный ответ ученика, можно сказать, что мы теперь знаем все основные понятия объектно-ориентированного профаммирования (ООП), нам только не известны их названия. Настало время систематизировать основные идеи ООП, что, безусловно, поможет не только лучше понять С++, но и освоить другие объектно-ориентированные языки, такие как Smalltalk, JAVA и Eiffel. Начнем с объектно-ориентированного подхода - системы идей, касающихся общих методов познания, применимых не только в профаммировании, но в любой наушой дисциплине - химии, ботанике, социологии. Объектно-ориентировапньгй подход держится па трех китах: классификации, специализащи, полиморфизме. Классификация есть способность вьщелить группы объектов с одинаковыми свойствами и операциями. При подготовке .9то1чз раздела использовалась статья Ashley М. Aitken Object Orientation Revealed!* 11 Ргос. 10 th Australasian Conference on Information Systems, 1999. Заключение 245 Люди способны классифицировать почти инстинктивно. Мы легко отличаем стул от стола, раковину от ванны, снам от полезных сообщений и даже ящик стола от корзины для мусора. Специализащ1я есть способность продолжить классификацию дальше, то есть из класса животных выделить насекомых, млекопитаюн1Их и т. д., из млекопитающих выделить человекообразных, а из них - вид homo sapience. Полиморфизм есть способность разных объектов по-разному реагировать на одинаковые действия. Например, загрузка файла в текстовый редактор отличается от загрузки файла в редактор графический, потому что форматы текстовых и графических файлов различны. Но действия при этом выполняются одинаковые: в меню Файл выбирается пункт Открыть. После определения основных понятий объектно-ориентированного подхода перейдем к объекгно-ори-ентирова1ПЮму нрофаммироваьгию. Нужно сказать, что основные идеи объектного подхода по-разному реализуются в разных языках. Мы, конечно, будем опираться на С++. Начнем со средств, позволяющих реализовать классификацию. Очевидно, классификация невозможна, если язык программирования не способен создать модель объекта. Так вот, механизм создания таких моделей называется инкапсуляцией. Инкапсуляция - это способность языка создать модель объекта, в которой соединены его свойства и поведение. Такой моделью в языке С++ служит njxJToTnn объекта, задаваемый словом class. Причем свойства объекта связаны с его данными, а поведение с собственными функциями. Второе свойство языка, необходимое для вьгделе-ния объектов, называется сокрытием данных. Вспомним про области private в классах, куда помсгцаются элементы данных, а также функции, выполняющие внутренние для объекта операции. Не будь возможности сокрытия данных, 1Юлноцснна>1 реализация объектов, а значит, и их классификация, стали бы невоз.мож-ными. Без сокрытия данных объекты теряют обособленность, становятся как бы прозрачными и общедостун-ными. Сокрытие данных поддерживает целостность o6ijeKTa. Сокрытие да ьг н ы X п р и вод ИТ к тому, что объекту нужно передавать сообщения, на которые гот должен реагировать. Действительно, должен же быть какой-то доступ к скрытым данным, иначе они окажутся просто невидимыми. Сообщения, принимаемые объектом, определяют его поведение, которое не должно меняться при изменениях в скрытых данных и функциях. Таковы средства языка, обеспечивающие классификацию. Они не так очевидны, если сравнить их с наследованием (см. главу 10), безусловно создапны.м для поддержания специализации. Можно, конечно, с но.моп1ЬЮ механизма наследования смешать бульдога с носорогом, но смысл наследования все-таки в уточнении, когда методы базового класса естественно применяются классом производным. Именно таков оператор доступа О, использовагнгый в разделе Составные объекты главы 10. И наконец, упомянем полиморфизм, богато представленный в С++. Прежде всего вспомним о переопределении функций (раздел Функции-тезки в главе 5). Оказывается, в С++ можно заготовить несколижо одноименных функций и потом не беспокоиться о выборе нужной, потому что компилятор сам определит, какую вызвать, по се аргумента.м. Такого же Э(1х1)екта можно добиться использованием шаблонов (см. раздел Шаблоны функций в главе 11). При таком подходе полиморфное поведение достига- ется тем, что компилятор сам создает функцию, если, конечно, находит подходящий шаблон. Создать полиморфные объекты помогают операторные функции, о которых рассказывается в главе 9. Определив в разных классах операторную функцию для oi le-ратора +, можно писать с=а+Ь, не задумываясь о том, что такое а и b - ма фицы, комплексные числа, массивы или что-то еще. Полиморфизм обеспечивают также шаблоны классов (см. раздел Шаблоны классов в главе 11). Вспомним контейпсрные типы, в которых многие действия выполняются одинаково для разных типов объектов. 11апример, сортировка в контейнере выполняется одинаково, если для всех разнородных объектов правильно реализован оператор сравнения. С помощью шаблогюв, а также операторных и одно-н.менных функций рсатизуется так называемый статический полиморфизм, называемый enie статическим связыванием, потому что класс или функция создаются во время компиляции, до запуска програ.ммы. В противоположность статическому динамическое связывание происходит во время исиолнення программы. Пример можно найти в разделе Изменчивость и отбор главы 10. Там, как вы помните, в массив указателей на базовый класс записывались указатели как на базовый, так и на производный классы. Если с помощью таких указателей вызывать собственные функции, одинаково назьшаелп>1е как в базовом, так и в производном классах, вызывается функция, соответствующая адресу объекта. Для объекта производного класса вызывается своя функция, для объекта базового класса - своя. Дина.%п1ческое связывание считается фирменной особенностью объектно-орпептированного программирования. Во многих языках оно действует по умолча-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |