Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
samples / Zaochniki / ООП.doc
Скачиваний:
28
Добавлен:
25.03.2015
Размер:
183.81 Кб
Скачать

№5 Конструкторы класса

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

• создание объектов с инициализацией по умолчанию • создание объектов со специальной инициализацией

• создание объектов путем копирования других объектов

Конструктор имеет специальное зарезервированное имя, совпадающее с именем класса, к которому принадлежит конструктор. Итак, конструктор для класса Counter объявляется следующим образом: class Counter { public:

Counter ( ); // объявление конструктора};

Различные виды конструкторов объявляются по-разному, а объединяет их то, что они не имеют возвращаемого значения. Нельзя объявить конструктор, возвращающий какое-либо значение, даже void. Задача конструктора — построить в памяти объект, что не влечет возвращения значения. Конструкторы нельзя объявлять статическими или виртуальными.

Конструкторы классов с подобъектамию Подобъект — это объект класса, объявленный внутри другого класса. При создании экземпляра включающего класса конструктор должен построить объект класса. Если класс имеет подобъекты, то конструктор включающего класса должен вызвать конструкторы подобъектов. Конструкторы по­добъектов вызываются в том порядке, в каком подобъекты появляются в объявлении класса. При создании экземпляра класса, производного от другого класса, конструктор базового класса вызывается ав­томатически.

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

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

Конструктор, объявляемый без аргументов, называется конструктором по умолчанию. Поскольку такой конструктор не имеет аргумен­тов, каждый класс может иметь только один конструктор по умолчанию. Если конструктор по умолчанию не определен в описании класса, то Borland C++ объявляет его автоматически. Созданный компилятором конструктор по умолчанию просто выделяет память при создании объекта своего клас­са.

Конструкторы с аргументами

Основная задача конструктора — инициализировать объект перед использованием, в результате чего можно вызвать функции, динамически распре­делить память, присвоить переменным конкретные значения и т.д.

Если конструкторы принимают разные типы и разное количество аргументов, то их для одного и того же клас­са может быть объявлено несколько. Предположим, что нужно с помощью аргументов типов float, long, int, символьной строки (или вообще без аргументов) создать класс Counter, который был бы достаточно гибок и инициализировался по-разному. Для этого следует объявить следующие конструкторы:

Counter (int = 0); // принимает целое или обнуляется по умолчанию

Counter (char*); // принимает символьную строку

Давайте рассмотрим, как определяются следующие конструкторы:

Counter : :Counter (int initial_value)

{ count = initial value;}

Counter : : Counter (char* initial_value)

{count = atol (initial_value);}

И, наконец, как они используются:

void main( ) {

Counter object ("5"); // конструктор для char*

Counter object1 (5); // конструктор для int

Counter object4; // конструктор для int по умолчанию }

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

Конструкторы копирования. Часто, создавая объект, вовсе не обязательно специально инициализировать какие-то переменные. Нужен про­сто "такой же" объект, как и этот. Это подразумевает получение копий уже существующего объекта, что, в свою очередь, требует особого конструктора, обычно называемого инициализатором копии (copy initializer) или кон­структором копирования (copy constructor).

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

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

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

Термин наследование применяется здесь только к классам и их характеристикам. Переменные не могут наследовать что-либо от других переменных, а функции не могут наследоваться от других функций. Наследование позволяет, практически без ограничений, последовательно строить и расширять классы, создан­ные вами или кем-то еще. Язык C++ отличается от других объектно-ориентированных языков еще и тем, что допускает не только простое, но и множественное наследование, когда данный класс порождается сразу от нескольких родитель­ских классов, наследуя поведение всех своих предков.

Повторное использование —это использование в программе класса для создания экземпляров или в качестве базового для создания нового класса, наследующего часть или все характеристики родителя. Повторное использование в C++ овеществляется через наследование.

class Box { public;

int width, height;

void SetWidth (int w) { width = w; }

void SetHeigt (int h) { height = h; } };

class ColoredBox: public Box { public:

int color;

void SetColor (int c) { color = c; } };

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

ColoredBox cb;

void main ()

{// использование функций-членов ColoredBox

cb.SetColor (5); // собственная

cb.SetWidth (3); // унаследована

cb.SetHeight (50); // унаследована }

Унаследованные функции используются точно так же, как и собственные.

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

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

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

Если класс является производным, то он имеет одного или несколько родителей. Здесь описание наследования начато с самого простого случая — простого наследования. Большинство правил простого наследования примени­мо и ко множественному наследованию, хотя между этими видами передачи характеристик существует немалая разница.

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

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

При создании экземпляра производного класса автоматически вызывается конструктор базового класса. После того как объект сконструирован, конструктор базового класса становится недоступным. Хотя конструктор базово­го класса и наследуется, вызывается он только компилятором, когда конструируется объект производного класса. Конструктор, в отличие от других унаследованных функций, вызвать явно нельзя.

Спецификаторы доступа базовых классов. Когда класс порождается от базового, все имена базового класса в производном классе автоматически станов­ятся приватными. Именно такое поведение C++ по умолчанию. Но его легко изменить, указав следующие спецификаторы доступа базового класса:

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

public. Все общедоступные имена базового класса будут общедоступными в производном классе и все защищенные имена будут защищенными в производном классе

Для спецификаторов доступа базового класса нет ключевого слова protected

Классы для наследования. Учитывая то, что в C++ особое внимание уделено наследованию и повторному использованию, программист тратит много времени на разработку классов, которые являются базовыми для других классов. Привилегий досту­па private и public, которые были установлены для первых версий C++, оказалось недостаточно, и была введе­на еще одна привилегия — protected. Любой идентификатор, появившийся в секции protected базового клас­са, доступен функциям класса (но не пользователям). Защищенные имена можно использовать во всех классах, по­рожденных от данного базового класса. Характеристика protected распространяется вниз по дереву наследова­ния неограниченно.

Соседние файлы в папке Zaochniki