Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория_к_экзамену_ООП.doc
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
422.4 Кб
Скачать

Вопрос 15 массивы

Массив – упорядоченное множество однотипных элементов. Это тоже ТИП.

Одной из характеристик массива является ранг или размерность массива. Массив размерности (или ранга) N (N определяет число измерений массива) – это Массив массивов (или составляющих массива) ранга N–1. Составляющие массива – это массивы меньшей размерности, являющиеся элементами данного массива. При этом составляющая массива сама может быть либо массивом, либо элементом массива. Объявление массива:

ДВЕ различных категории массивов:

  • простые (прямоугольные) массивы,

  • jagged (вложенные) массивы.

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

int[] myArray = new int [5];

Операция new используется для создания массива и инициализации его элементов предопределенными значениями. В результате выполнения этого оператора все элементы массива будут установлены в ноль.

Вопрос 16 перегрузка операций

Перегрузка операций в C# является способом объявления семантики новых операций, которые обозначаются принятыми в C# символами операций.

Перегрузка операций строится на основе общедоступных (public) статических (вызываемых от имени класса) функций-членов с использованием ключевого слова operator.

Не все операции множества могут быть переопределены (перегружены) подобным образом. Некоторые операции могут перегружаться с ограничениями.

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

+, –, !, ~, ++, ––, true, false

Унарные символы операций, допускающие перегрузку. true и false также являются операциями

+, –, *, /, %, &, |, ^, <<, >>

Бинарные символы операций, допускающие перегрузку

==, !=, <, >, <=, >=

Операции сравнения перегружаются

&&, ||

Условные логические операции моделируются с использованием ранее переопределенных операций & и |

[]

Операции доступа к элементам массивов моделируются за счет индексаторов

+=, –=, *=, /=, %=, &=, =, ^=, <<=, >>=

Операции не перегружаются, по причине невозможности перегрузки операции присвоения

=, ., ?:, –>, new, is, sizeof, typeof

Операции, не подлежащие перегрузке

При этом при перегрузке операций для любого нового типа выполняются следующие правила:

  • префиксные операции ++ и –– перегружаются парами;

  • операции сравнения перегружаются парами: если перегружается операция ==, также должна перегружаться операция !=. То же самое относится к парам < и >, <= и >=.

Вопрос 17 Наследование. Конструкторы базового и производного классов

Наследование является одним из принципов ООП. С помощью него реализуются основы классификации, а так же механизмы повторного использования и модификации кода. Базовый класс задает общие признаки и общее поведение для классов-наследников. То есть общие (наиболее общие) свойства и методы наследуются от базового класса, но в дополнение к ним добавляются и определяются НОВЫЕ свойства и методы. Таким образом, прежде всего наследование реализует механизмы расширения базового класса.

Производный класс наследует от базового класса ВСЕ, что он имеет. Другое дело, что воспользоваться в производном классе можно не всем наследством. Например, объект класса наследника в принципе НЕ может получить доступ к private данным — членам и функциям — членам класса-родителя. Косвенное влияние на такие данные-члены и функции — члены – лишь через public-функции класса-родителя. Следует иметь в виду еще одно важное обстоятельство. Если упорядочить все (известные) спецификаторы доступа C# по степени их открытости: public…private, то наследуемый класс не может иметь более открытый спецификатор доступа, чем его предок.

Спецификатор доступа – protected обеспечивает открытый доступ к членам базового класса, но только для производного класса. Защищенные члены базового класса доступны для ВСЕХ прямых и косвенных наследников данного класса.

При определении классов спецификаторы доступа действуют и в рамках пространства имен. Но в пространстве имен явным образом можно использовать лишь один спецификатор – спецификатор public, либо не использовать никаких спецификаторов.

При создании любого класса, как правило, проектируется его конструктор. Передача управления конструктору базового класса при создании объекта — представителя производного класса осуществляется посредством конструкции ...(...):base(...){...}, которая располагается в объявлении конструктора класса-наследника между заголовком конструктора и телом. После ключевого слова base в скобках располагается список значений параметров конструктора базового класса. Очевидно, что выбор соответствующего конструктора определяется типом значений в списке (возможно, пустом) параметров.

Пример работы с конструкторами:

Построим два новых класса:

class X

{

}

class Y:X

{

}

// Это уже в Main()

Y y = new Y();

Вся работа по созданию объекта – представителя класса Y при явном отсутствии конструкторов по умолчанию возлагается на КОНСТРУКТОРЫ УМОЛЧАНИЯ – те самые, которые самостоятельно строит транслятор.

Особых проблем не будет, если в производном классе явным образом начать объявлять конструкторы:

class X

{

}

class Y:X

{

public Y(int key){}

public Y(){}

}

// Это уже в Main()

Y y0 = new Y();

Y y1 = new Y(125);

С этого момента в производном классе нет больше конструктора умолчания. Теперь все зависит от соответствия оператора определения объекта построенному нами конструктору.

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

Проблемы в производном классе возникнут, если в базовом классе попытаться объявить вариант конструктора с параметрами:

class X

{

public X(int key){}

}

class Y:X

{

public Y(int key){} // Нет конструктора умолчания базового класса!

public Y(){} // Нет конструктора умолчания базового класса!

}

// Это уже в Main()

Y y0 = new Y();

Y y1 = new Y(125);

И здесь транслятор начнет обижаться на конструкторы производного класса, требуя ЯВНОГО объявления конструктора базового класса БЕЗ параметров. Если вспомнить, что при ЛЮБОМ вмешательстве в дело построения конструкторов транслятор снимает с себя всю ответственность, причина негодования транслятора становится очевидной. Возможны два варианта решения проблемы:

  1. явным образом заставить работать новый конструктор базового класса,

  2. самостоятельно объявить новый вариант конструктора без параметров:

class X

{

public X(){}

public X(int key){}

}

class Y:X

public Y(int key){}

public Y():base(125){}

}

// Это уже в Main()

Y y0 = new Y();

Y y1 = new Y(125);