Основные принципы ООП

Неправильное употребление фразеологизма.

Фразеологизм – это устойчивое выражение, употребляемое в неизменном виде. Например: В нашем споре этот аргумент имел огромную роль. Правильно: В нашем споре этот аргумент имел огромное значение.

 

8. Засорение речи словами-паразитами, типа НУ..., ЭТО…, ЭТО САМОЕ… и др.

 

 

Объектно-ориентированное программирование основано на «трех китах» – трех важнейших принципах, придающих объектам новые свойства. Этими принципами являются инкапсуляция, наследование и полиморфизм.

Инкапсуляция

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

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

Другим немаловажным следствием инкапсуляции является легкость обмена объектами, переноса их из одной программы в другую. Можно сказать, что ООП «провоцирует» разработку библиотек объектов, таких в С++ – огромное множество.

Наследование

Наследование есть свойство объектов порождать своих потомков. Объект-потомок автоматически наследует от родителя все поля и методы, может дополнять объекты новыми полями и заменять (перекрывать) методы родителя или дополнять их.

Принцип наследования решает проблему модификации свойств объекта и придает ООП в целом исключительную гибкость. При работе с объектами программист обычно подбирает объект, наиболее близкий по своим свойствам для решения конкретной задачи, и создает одного или нескольких потомков от него, которые «умеют» делать то, что не реализовано в родителе.

Последовательное проведение в жизнь принципа «наследуй и изменяй» хорошо согласуется с поэтапным подходом к разработке крупных программных проектов и во многом стимулирует такой подход.

Полиморфизм

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

2.2. Преобразование программ, написанных на языке С, в программы на C++

Если у вас имеется собственная программа на языке С, возможно она же будет вашей первой программой на C++! Кроме некоторых исключений, язык С является своеобразным подмножеством C++, т.е. C++ поддерживает почти все компоненты С, дополняя их многими собственными компонентами. Следовательно, начиная работать с C++, можно компилировать программы на С, как и на C++ с помощью компилятора C++ вместо С. Затем можно постепенно добавлять в программы различные компоненты, характерные для C++.

Чтобы использовать компилятор C++, нужно присвоить исходному файлу имя с расширением .срр вместо . Однако существуют приемы программирования, допустимые во многих версиях С, которые не будут компилироваться с помощью C++ или будут компилироваться с изменением смысловых значений. Далее описаны некоторые наиболее важные конструкции языка С, которые не поддерживаются в C++.

  • В языке C++ намного больше зарезервированных ключевых слов, чем в С. В программах их нельзя использовать как идентификаторы. Ниже приведен список зарезервированных ключевых слов, который содержит ключевые слова языка С и дополнительные ключевые слова, существующие только в C++.

 

auto else new throw
bad_cast enum operator true
bad_typeid except private try
bool explicit protected type_info
break extern public typedef
сазе false register typeid
catch finally reinterpret_cast typename
char float return union
class for short unsigned
const friend signed using
const_cast goto sizeof virtual
continue if static void
default inline static cast volatile
delete int stuct while
do long switch  
double mutable template  
dynamic__cast namespace this  

 

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

Примечание

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

· В языке С можно объявить функцию, использующую один или более параметров, предварительно их не перечисляя, например:

int FuncX(); /* эта функция языка С на самом деле будетиспользовать несколько параметров */

Однако в языке C++ такое объявление допустимо только для функций, которые не имеют параметров.

· В языке С можно использовать «старый стиль» синтаксиса определения функции, в котором типы параметров следуют за списком параметров, например:

int FuncX(А,В); /* правильно в С, ошибка в C++ */ int А; int В;{/* код FuncX */return 0;}

В языке C++ использование такого стиля недопустимо.

· В некоторых версиях С глобальный объект данных можно объявить в программе более одного раза без использования спецификатора extern. В языке C++ для определения переменной можно объявить глобальный объект данных без спецификатора extern только один раз. Чтобы сделать переменную доступной в определенной области видимости, все другие объявления элемента должны включать ключевое слово extern. (Термин область видимости указывает на фрагмент текста программы, в котором используется определенное имя.)

· В языке С (в соответствии со стандартом ANSI) можно присвоить указатель типа void указателю любого типа. Например, следующий код задает присваивание указателя типа int указателю типа void:

int А;int *PInt;void *PVoid = &A; Pint = PVoid; /* правильно для С; ошибка для C++ */

В языке C++ присваивание PInt генерирует ошибку, потому что компилятор C++ не будет автоматически преобразовывать указатель типа void в указатель другого типа в выражении присваивания. Для выполнения присваивания используется операция изменения типа.

PInt = (int *)PVoid; /* правильно в С и C++ */

· В языке С названия тегов конструкций enum, struct или union могут совпадать с названиями типов данных, определенными оператором typedef, в пределах одной области видимости. Например, следующий код успешно компилируется в С:

/* этот код правильный в С, но ошибочный в C++: */ typedef int TypeA;struct TypeA {int I; char C; double D; };typedef int TypeB; union TypeB{int I;char C;double D;};typedef int TypeC;enum TypeC (Red, Green, Blue);

Компилятор языка С может различать дублирующие имена, потому что при описании перечислений, структур и объединений используются префиксы enum, struct или union, например:

/* этот код правилен в С, но ошибочен в C++: */typedef int TypeA; struct TypeA{int I;char C;double D;};TypeA X; /* создает переменную типа int */struct TypeA Y; /* создает структуру TypeA */sizeof (TypeA); /* вычисляет размер переменной типа int */ sizeof (struct TypeA); /* вычисляет размер структуры TypeA */

В языке C++ теги конструкций enum, struct, union или class (в C++ их чаше называют именами, а не тегами) должны отличаться от любого имени, заданного в операторе typedef внутри той же области видимости. (Ключевое слово class уникально для языка C++). Определение создает новый тип, на который можно сослаться, используя одно имя этого типа, поэтому не рекомендуется использовать префикс enum, struct, union или class (хотя при желании это можно делать). Описанное свойство продемонстрировано следующим фрагментом программы:

/* этот код ошибочен в С, но правилен в C++: */struct TypeA {int I; char С; double D; };struct TypeA X; /* создает структуру TypeA */TypeA Y; /* также создает структуру TypeA */sizeof (struct TypeA}; /* вычисляет размер структуры TypeA */sizeof (TypeA}; /* вычисляет размер структуры TypeA */

Следовательно, если задать оператор typedef с таким же именем, то компилятор C++ не всегда сможет различить эти два типа, например:

typedef int ТуреА;struct ТуреА /* ошибка в C++: повторное определение ТуреА */{int I;char С;double D;};ТуреА X; /* создаются при этом данные типа intили структура ТуреА? */sizeof (ТуреА); /* вычисляется размер данных типа intили размер структуры ТуреА ?*/

· Еще одна несовместимость связана с предыдущей: в языке С, если теги enum, struct или union такие же, как имя, определенное typedef во внешней области видимости, то вы все еще можете оставить ссылку на typedef во внутренней области видимости (т.е. имя, определенное typedef, не скрыто). Однако в языке C++ имя typedef должно быть скрыто. Следующий фрагмент программы иллюстрирует различие.

typedef int ТуреА;void main () { struct TypeA {

int I;

char C;

double D;

}; TypeA X; /* в языке С идентификатор X имеет тип int; в C++ X - это структура ТуреА */ sizeof (ТуреА}; /* в С - вычисляет размер данных типа int; в C++ - вычисляет размер структуры ТуреА */}

· В способах вычисления значений, возвращаемых оператором sizeof, есть два дополнительных различия. Первое: в языке С sizeof ('х') равно sizeof (int), а в C++ оно равно sizeof {char}. Далее, предположим, что определено перечисление

enum Е {X, Y, Z};

Тогда (второе различие) в С значение sizeof (X) будет равно sizeof (int), а в C++ равно sizeof (E), что не обязательно равно sizeof (int).

Работа с несовместимыми конструкциями. Из существующей программы на С можно удалить любую из несовместимых с C++ конструкций так, что код будет компилироваться и иметь такое же смысловое содержание, как и при использовании компилятора C++. Компилятор C++ заметит все перечисленные варианты несовместимости, кроме двух последних, которые (особенно различия в значениях, создаваемых оператором sizeof) не приводят к появлению сообщений компилятора об ошибке, но изменяют смысловое содержание программы. Такая ситуация – исключение из общего правила: если программа успешно компилируется компиляторами С и C++, то она имеет одинаковое смысловое содержание в обоих языках.

2.3. Новые средства языка C++

В данном параграфе рассмотрены новые полезные средства языка C++, не являющиеся классами, из чего можете сделать вывод о том, что только они одни оправдывают переход к программированию на языке C++. Некоторые из этих компонентов включены в последние версии языка С (в частности, новый стиль комментариев, встроенные (inline) функции и типы констант, хотя они могут синтаксически отличаться от представления в языке C++). Другие компоненты, описанные здесь, уникальны в языке C++.