1 какие программы называются унаследованными

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

Объекты производного класса свободно могут использовать всё, что создано и отлажено в базовом классе. При этом, мы можем в производный класс, дописать необходимый код для усовершенствования программы: добавить новые элементы, методы и т.д.. Базовый класс останется нетронутым. Эту тему вполне возможно освоить новичкам.

Необходимо только познакомиться с синтаксисом и некоторыми особенностями. Ниже приведен простой код программы, который мы детально разберем под листингом. В этой программе созданы два класса: базовый — FirstClass и производный от него SecondClass .

#include using namespace std; class FirstClass // базовый класс < protected: // спецификатор доступа к элементу value int value; public: FirstClass() < value = 0; >FirstClass( int input ) < value = input; >void show_value() < cout >; class SecondClass : public FirstClass // производный класс < public: SecondClass() : FirstClass () // конструктор класса SecondClass вызывает конструктор класса FirstClass <>SecondClass(int inputS) : FirstClass (inputS) // inputS передается в конструктор с параметром класса FirstClass <> void ValueSqr () // возводит value в квадрат. Без спецификатора доступа protected эта функция не могла бы изменить значение value < value *= value; >>; int main() < setlocale(LC_ALL, «rus»); FirstClass F_object(3); // объект базового класса cout << «value F_object = «; F_object.show_value(); SecondClass S_object(4); // объект производного класса cout << «value S_object = «; S_object.show_value(); // вызов метода базового класса S_object.ValueSqr(); // возводим value в квадрат cout << «квадрат value S_object = «; S_object.show_value(); //F_object.ValueSqr(); // базовый класс не имеет доступа к методам производного класса cout

1. Начало обучения. Почему проект называется Живой Учебник?

Разбирать пример будем по-порядку. Ранее мы работали только со спецификаторами доступа private и public . В строке 6 мы встретили новый для нас спецификатор доступа protected . Он отличается от private тем, что разрешает доступ к элементам базового класса из производных классов. Если бы элемент value находился в поле private , то доступ к нему был бы закрыт и мы бы не могли изменить его значение через объект класса SecondClass , используя функцию ValueSqr() , определённую в строках 34 — 37.

Чтобы было наглядней, отличия спецификаторов доступа можно отобразить в таблице:

private protected public
Доступ из тела класса открыт открыт открыт
Доступ из производных классов закрыт открыт открыт
Доступ из внешних функций и классов закрыт закрыт открыт

Правильные знания и обязательные программы для компьютера

Если вы создаёте класс, который в дальнейшем планируете использовать, как базовый, то объявляйте в нём поле protected вместо private . Иначе объекты производного класса не смогут обращаться к элементам базового.

Ниже, в строках 8 — 22, определены методы базового класса. Конструктор без параметров FirstClass() , конструктор с параметром FirstClass( int input ) и метод void show_value() , который выводит значение value на экран.

Определение производного находится в строках 25 — 38. Синтаксис наследования такой — class Имя_Производного_Класса : спецификатор доступа Имя_Базового_Класса < >; Двоеточие : не путайте с двойным двоеточием :: (определение области действия). Используя этот оператор мы показываем, наследником какого класса является производный класс.

Важной особенностью производного класса, является то, что хоть он и может использовать все методы и элементы полей protected и public базового класса, но он не может обратиться к конструктору с параметрами. Если конструкторы в производном классе не определены, при создании объекта сработает конструктор без аргументов базового класса.

А если нам надо сразу при создании объекта производного класса внести данные, то для него необходимо определить свои конструкторы. В нашем примере показано, как же мы всё-таки можем использовать уже готовые конструкторы базового класса, чтобы не набирать код конструкторов снова — строки 28 — 32. Для этого при определении конструктора производного класса после его имени следует поставить оператор : и имя конструктора базового класса, который необходимо вызвать, при создании объекта производного класса — SecondClass() : FirstClass ()<> . Тело конструктора оставляем пустым т.к. всю работу проделает конструктор базового класса. В случае конструктора с параметром, этот параметр мы передаем в конструктор с параметром базового класса SecondClass(int inputS) : FirstClass (inputS)<> — строка 31.

В main-функции создаем объекты базового и производного классов — FirstClass F_object(3); и SecondClass S_object(4); и отображаем их значения value на экран. Как видите в строке 50, объект производного класса без проблем обращается к методу show_value() базового класса. Так, будто это его собственный метод. Ниже вызываем метод, который возводит значения value производного класса в квадрат.

Читайте также:
Программа чтобы зайти на чужой комп

И выводим это изменённое значение на экран. А вот если мы захотим вызвать этот метод — F_object.ValueSqr(); — для объекта базового класса, компилятор нам этого не позволит сделать и выдаст ошибку. Это еще одна важная особенность — производный класс имеет доступ к базовому классу, а базовый класс, даже «не знает» о существовании производного и не может пользоваться его кодом.

Результат работы программы:

CppStudio.com

value F_object = 3
value S_object = 4
квадрат value S_object = 16

В виде списка приведу основную информацию о наследовании классов, которую важно знать:

  • Наследование — это определение производного класса, который может обращаться ко всем элементам и методам базового класса за исключением тех, которые находятся в поле private ;
  • Производный класс еще называют потомком или подклассом, а базовый — родитель или надкласс;
  • Синтаксис определения производного класса: class Имя_Производного_Класса : спецификатор доступа Имя_Базового_Класса < /*код*/ >;
  • Производный класс имеет доступ ко всем элементам и методам базового класса, а базовый класс может использовать только свои собственные элементы и методы.
  • В производном классе необходимо явно определять свои конструкторы, деструкторы и перегруженные операторы присваивания из-за того, что они не наследуются от базового класса. Но их можно вызвать явным образом при определении конструктора, деструктора или перегрузки оператора присваивания производного класса, например таким образом (для конструктора): Конструктор_Производного_Класса (/*параметры*/) : Конструктор_Базового_Класса ( /*параметры*/) < >.
  • Еще один важный момент при наследовании — перегруженные функции-методы класса потомка. В данном примере мы его не рассматривали. Но чтобы вы знали, если в классе родителе и в его классах потомках встречаются методы с одинаковым именем, то для объектов класса потомка компилятор будет использовать методы именно класса потомка. Перегруженные методы класса потомка, могут вызывать методы класса родителя. В таком случае важно помнить, что необходимо правильно определить область действия с помощью оператора :: .Иначе компилятор воспримет это, как вызов функцией самой себя. Наглядно, если бы мы перегрузили в классе SecondClass функцию show_value() — это выглядело бы так:

void show_value()

Эта запись указывает компилятору — если значение value не равно нулю — вызвать метод show_value() класса FirstClass . А он в свою очередь, отобразит это значение на экране.

Думаю для первого знакомства с наследованием классов этого достаточно. Это бесспорно классная возможность языка С++. Она помогает экономить массу времени на написание и отладку кода с нуля. Вместо этого мы можем использовать уже готовый и отлаженный код и подстраивать его под новые задачи, которые поставлены перед нами. При этом наша новая программа будет занимать намного меньше строк, что значительно улучшит её читабельность.

Источник: cppstudio.com

Инкапсуляция, полиморфизм, наследование

Все языки OOP, включая С++, основаны на трёх основополагающих концепциях, называемых инкапсуляцией, полиморфизмом и наследованием. Рассмотрим эти концепции.

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

Инкапсуляция (encapsulation) — это механизм, который объединяет данные и код, манипулирующий зтими данными, а также защищает и то, и другое от внешнего вмешательства или неправильного использования. В объектно-ориентированном программировании код и данные могут быть объединены вместе; в этом случае говорят, что создаётся так называемый «чёрный ящик». Когда коды и данные объединяются таким способом, создаётся объект (object). Другими словами, объект — это то, что поддерживает инкапсуляцию.

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

На самом деле объект является переменной определённого пользователем типа. Может показаться странным, что объект, который объединяет коды и данные, можно рассматривать как переменную. Однако применительно к объектно-ориентированному программированию это именно так. Каждый элемент данных такого типа является составной переменной.

2. Полиморфизм

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

Выполнение каждого конкретного действия будет определяться типом данных. Например для языка Си, в котором полиморфизм поддерживается недостаточно, нахождение абсолютной величины числа требует трёх различных функций: abs(), labs() и fabs(). Эти функции подсчитывают и возвращают абсолютную величину целых, длинных целых и чисел с плавающей точкой соответственно.

Читайте также:
Как обрезать музыку из видео без программ

В С++ каждая из этих функций может быть названа abs(). Тип данных, который используется при вызове функции, определяет, какая конкретная версия функции действительно выполняется. В С++ можно использовать одно имя функции для множества различных действий. Это называется перегрузкой функций (function overloading).

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

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

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

В С++ вы можете применить эту концепцию и к другим, заданным вами, типам данных. Такой тип полиморфизма называется перегрузкой операторов (operator overloading).

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

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

Наследование (inheritance) — это процесс, посредством которого один объект может приобретать свойства другого. Точнее, объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Наследование является важным, поскольку оно позволяет поддерживать концепцию иерархии классов (hierarchical classification).

Применение иерархии классов делает управляемыми большие потоки информации. Например, подумайте об описании жилого дома. Дом — это часть общего класса, называемого строением. С другой стороны, строение — это часть более общего класса — конструкции, который является частью ещё более общего класса объектов, который можно назвать созданием рук человека.

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

Источник: codenet.ru

Основные принципы ООП: инкапсуляция, наследование, полиморфизм

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

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

Абстракция данных — популярная и в общем неверно определяемая техника программирования. Фундаментальная идея состоит в разделении несущественных деталей реализации подпрограммы и характеристик существенных для корректного ее использования. Такое разделение может быть выражено через специальный «интерфейс», сосредотачивающий описание всех возможных применений программы [1].

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

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

Пользователь может взаимодействовать с объектом только через этот интерфейс. Реализуется с помощью ключевого слова: public.

Пользователь не может использовать закрытые данные и методы. Реализуется с помощью ключевых слов: private, protected, internal.))

Инкапсуляция — один из четырёх важнейших механизмов объектно-ориентированного программирования (наряду с абстракцией, полиморфизмом и наследованием).

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

предельная локализация изменений при необходимости таких изменений,

прогнозируемость изменений (какие изменения в коде надо сделать для заданного изменения функциональности) и прогнозируемость последствий изменений.

Читайте также:
Ноутбук устанавливает программы сам

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

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

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

Простое наследование: [ ]

Класс, от которого произошло наследование, называется базовым или родительским (англ. base class). Классы, которые произошли от базового, называются потомками, наследниками или производными классами (англ. derived class).

В некоторых языках используются абстрактные классы. Абстрактный класс — это класс, содержащий хотя бы один абстрактный метод, он описан в программе, имеет поля, методы и не может использоваться для непосредственного создания объекта. То есть от абстрактного класса можно только наследовать. Объекты создаются только на основе производных классов, наследованных от абстрактного.

Например, абстрактным классом может быть базовый класс «сотрудник вуза», от которого наследуются классы «аспирант», «профессор» и т. д. Так как производные классы имеют общие поля и функции (например, поле «год рождения»), то эти члены класса могут быть описаны в базовом классе. В программе создаются объекты на основе классов «аспирант», «профессор», но нет смысла создавать объект на основе класса «сотрудник вуза».

Множественное наследование [ ]

При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из других языков, предоставляющих эту возможность, можно отметить Python и Эйфель.

Множественное наследование поддерживается в языке UML.

Множественное наследование — потенциальный источник ошибок, которые могут возникнуть из-за наличия одинаковых имен методов в предках. В языках, которые позиционируются как наследники C++ (Java, C# и др.), от множественного наследования было решено отказаться в пользу интерфейсов. Практически всегда можно обойтись без использования данного механизма. Однако, если такая необходимость все-таки возникла, то, для разрешения конфликтов использования наследованных методов с одинаковыми именами, возможно, например, применить операцию расширения видимости — «::» — для вызова конкретного метода конкретного родителя.

Попытка решения проблемы наличия одинаковых имен методов в предках была предпринята в языке Эйфель, в котором при описании нового класса необходимо явно указывать импортируемые члены каждого из наследуемых классов и их именование в дочернем классе.

Большинство современных объектно-ориентированных языков программирования (C#, Java, Delphi и др.) поддерживают возможность одновременно наследоваться от класса-предка и реализовать методы нескольких интерфейсов одним и тем же классом. Этот механизм позволяет во многом заменить множественное наследование — методы интерфейсов необходимо переопределять явно, что исключает ошибки при наследовании функциональности одинаковых методов различных классов-предков.

Полиморфизм [ ]

Полиморфи́зм — возможность объектов с одинаковой спецификацией иметь различную реализацию.

Язык программирования поддерживает полиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию — например, реализация класса может быть изменена в процессе наследования[1].

Кратко смысл полиморфизма можно выразить фразой: «Один интерфейс, множество реализаций».

Полиморфизм — один из четырёх важнейших механизмов объектно-ориентированного программирования (наряду с абстракцией, инкапсуляцией и наследованием).

Полиморфизм позволяет писать более абстрактные программы и повысить коэффициент повторного использования кода. Общие свойства объектов объединяются в систему, которую могут называть по-разному — интерфейс, класс. Общность имеет внешнее и внутреннее выражение:

  • внешняя общность проявляется как одинаковый набор методов с одинаковыми именами и сигнатурами (именем методов и типами аргументов и их количеством);
  • внутренняя общность — одинаковая функциональность методов. Её можно описать интуитивно или выразить в виде строгих законов, правил, которым должны подчиняться методы. Возможность приписывать разную функциональность одному методу (функции, операции) называется перегрузкой метода (перегрузкой функций, перегрузкой операций).

Формы полиморфизма [ ]

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

Параметрические методы. [ ]

Если полиморфизм включения влияет на наше восприятие объекта, то параметрический полиморфизм влияет на используемые методы, так как можно создавать методы родственных классов, откладывая объявление типов до времени выполнения. Для избежания написания отдельного метода каждого типа применяется параметрический полиморфизм, при этом тип параметров будет являться таким же параметром, как и операнды.

Параметрические типы. [ ]

Вместо того, чтобы писать класс для каждого конкретного типа следует создать типы, которые будут реализованы во время выполнения программы то есть мы создаем параметрический тип.

Полиморфизм переопределения. [ ]

Абстрактные методы часто одной версии отложенного метода в дочерних классах. Специальный полиморфизм допускает специальную реализацию для данных каждого типа.

Полиморфизм-перегрузка [ ]

Полиморфизм-перегрузка — это частный случай полиморфизма. С помощью xtik.

Источник: gos-it.fandom.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru