Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

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

Оценка алгоритма сортировки | Нахождение кратчайших путей от заданной вершины до всех остальных вершин алгоритмом Дейкстры | Доказательство | Метод Insert класса AVLTree | Итераторы вывода | Виды исключительных ситуаций |


Читайте также:
  1. Визуальное объектно-ориентирование программирование. Инкапсуляция, наследование, полиморфизм. Основные объекты и их свойства, методы и события
  2. Генитив множественное число
  3. Для классов, связанных наследованием, существует расширенная совместимость типов (совместимы по представлению в памяти).
  4. Замена множественного наследования наследованием от интерфейсов в других языках объектно-ориентированного программирования
  5. Имя существительное: склонение, множественное число. Артикль. Соединительный союз.
  6. Множественное наследование
  7. Множественное наследование

Мно́жественное насле́дование — концепция, поддерживаемая частью объектно-ориентированных языков программирования, при которой класс-потомок может иметь более одного суперкласса (непосредственного класса-родителя). Эта концепция является расширением «простого (или одиночного) наследования» (single inheritance), при котором класс может наследоваться только от одного суперкласса. Если противопоставляется одиночное наследование множественному, то означает противопоставление технологии, позволяющей обойти множественное наследование, а именно применение интерфейсов.

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

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

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

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

Виртуа́льное насле́дование (англ. virtual inheritance) в языке программирования C++ — один из вариантов наследования, который нужен для решения некоторых проблем, порождаемых наличием возможности множественного наследования (особенно «ромбовидного наследования»), путем разрешения неоднозначности того, методы которого из суперклассов (непосредственных классов-предков) необходимо использовать. Оно применяется в тех случаях, когда множественное наследование вместо предполагаемой полной композиции свойств классов-предков приводит к ограничению доступных наследуемых свойств вследствие неоднозначности. Базовый класс, наследуемый множественно, определяется виртуальным с помощью ключевого слова virtual.

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

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

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

На языке программирования C++ абстрактный класс объявляется включением хотя бы одной чистой виртуальной функции, типа virtual _сигнатура_функции_ =0;, которая как и другие может быть заменена. Пример на языке программирования C++:

#include <iostream> class CA { // Абстрактный класс public: CA (void) { std::cout << "This object of the class "; } virtual void Abstr (void) = 0; // Чистая (пустая) виртуальная функция. void fun (void) { std::cout << "Реализация не будет наследоваться!"; } ~CA () { std::cout << "." << std::endl; } //Вызывается в обр. порядке конструкторов }; class CB: public CA { public: CB (void) { std::cout << "CB;"; } void Abstr (void){ std::cout << " call function cb.Abstr();"; } //Подменяющая функция. void fun (void){ std::cout << " call function cb.fun()"; } ~CB () {} // Неверно для абстр. кл. ~CB(){ ~CA(); } }; class CC: public CA { public: CC (void) { std::cout << "CC;"; } void Abstr (void) { std::cout << " call function cc.Abstr();"; } //Подменяющая функция. void fun (void) { std::cout << " call function cc.fun()"; } ~CC () {} // Неверно для абстр. кл. ~CC(){ ~CA(); } }; int main () { std::cout << "Program:" << std::endl; CB cb; cb.Abstr(); cb.fun(); cb.~CB(); CC cc; cc.Abstr(); cc.fun(); cc.~CC(); return 0; }

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

Program:This object of the class CB; call function cb.Abstr(); call function cb.fun().This object of the class CC; call function cc.Abstr(); call function cc.fun().

4. Основні елементи об’єктної моделі. Поліморфізм. Віртуальні функції. Приклад реалізації на одній з мов програмування.

Полиморфи́зм (от греч. πολὺ- — много, и μορφή — форма) в языках программирования — возможность объектов с одинаковой спецификацией иметь различную реализацию.

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

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

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

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

внешняя общность проявляется как одинаковый набор методов с одинаковыми именами и сигнатурами (именами методов, типами аргументов и их количеством);

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

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

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

class самолет {
function move();
}
class танк {
function move();
}

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

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

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

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

Пример на C++, иллюстрирующий отличие виртуальных функций от невиртуальных:

class Ancestor{public: virtual void function1 () { cout << "Ancestor::function1()" << endl; } void function2 () { cout << "Ancestor::function2()" << endl; }}; class Descendant: public Ancestor{public: virtual void function1 () { cout << "Descendant::function1()" << endl; } void function2 () { cout << "Descendant::function2()" << endl; }}; Descendant* pointer = new Descendant ();Ancestor* pointer_copy = pointer; pointer->function1 ();pointer->function2 (); pointer_copy->function1 ();pointer_copy->function2 ();

В этом примере класс Ancestor определяет две функции, одну из них виртуальную, другую — нет. Класс Descendant переопределяет обе функции. Однако, казалось бы одинаковое обращение к функциям даёт разные результаты. На выводе программа даст следующее:

Descendant::function1() Descendant::function2() Descendant::function1() Ancestor::function2()

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

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

pointer->Ancestor::function1 ();

для нашего примера выведет Ancestor::function1(), игнорируя тип объекта.

5. Основні елементі об’єктної моделі. Поліморфізм. Перевизначення операторів. Приклад реалізації на одній з мов програмування операторів присвоювання, арифметичних дій, порівняння.

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

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

class самолет {
function move();
}
class танк {
function move();
}

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

Термин перегрузка — это калька английского слова overloading. Такой перевод появился в книгах по языкам программирования в первой половине 1990-х годов. В изданиях советского периода аналогичные механизмы назывались переопределением или повторным определением, перекрытием операций.

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


Дата добавления: 2015-11-16; просмотров: 105 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Алгоритмы неустойчивой сортировки| Перегрузка операции присваивания копированием

mybiblioteka.su - 2015-2024 год. (0.009 сек.)