KnigaRead.com/
KnigaRead.com » Разная литература » Прочее » Герберт Шилдт - C# 4.0 полное руководство - 2011

Герберт Шилдт - C# 4.0 полное руководство - 2011

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Герберт Шилдт - C# 4.0 полное руководство - 2011". Жанр: Прочее издательство неизвестно, год неизвестен.
Перейти на страницу:

MyClass t3 = new MyClass(17.23);

MyClass t4 = new MyClass(2, 4);

Console.WriteLine("tl.x: " + tl.x);

Console.WriteLine("t2.х: " + t2.x);

Console.WriteLine("t3.x: " + t3.x);

Console.WriteLine("t4.x: " + t4.x);

}

}

При выполнении этой программы получается следующий результат.

В конструкторе MyClass().

В конструкторе MyClass (int) .

В конструкторе MyClass(double).

В конструкторе MyClass (int, int). tl.x: О t2.x: 88 t3.x: 17 t4.x: 8

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

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

// Класс для хранения символов в стеке.

using System;

class Stack {

// Эти члены класса являются закрытыми, char[] stck; // массив, содержащий стек int tos;    // индекс вершины стека

// Сконструировать пустой объект класса Stack по заданному размеру стека, public Stack(int size) {

stck = new char[size]; // распределить память для стека tos = 0;

}

// Сконструировать объект класса Stack из существующего стека, public Stack(Stack ob) {

// Распределить память для стека, stck = new char[ob.stck.Length];

// Скопировать элементы в новый стек, for (int i=0; i < ob.tos; i++) stck[i] = ob.stck[i];

// Установить переменную tos для нового стека, tos = ob.tos;

// Поместить символы в стек, public void Push(char ch) { if(tos==stck.Length) {

Console.WriteLine(" - Стек заполнен."); return; -

}

stck[tos] = ch; tos++;

}

// Извлечь символ из стека, public char Pop ()    {

if(tos==0)    {

Console.WriteLine (" - Стек пуст."); return (char) 0;

}

tos—;

return stck[tos];

}

// Возвратить значение true, если стек заполнен, public bool IsFullO { return tos==stck.Length;

}

// Возвратить значение true, если стек пуст, public bool IsEmptyO { return tos==0;

}

// Возвратить общую емкость стека, public int Capacity()    {

return stck.Length;

}

// Возвратить количество объектов, находящихся в настоящий момент в стеке, public int GetNum() { return tos;

}

}

// Продемонстрировать применение класса Stack.

class StackDemo {

static void Main() {

Stack stkl = new Stack(10); char ch; int i;

// Поместить ряд символов в стек stkl.

Console.WriteLine("Поместить символы А-J в стек stkl."); for(i=0; !stkl.IsFull(); i++)

stkl.Push((char) ('A' + i));

// Создать копию стека stckl.

Stack stk2 = new Stack(stkl);

// Вывести содержимое стека stkl.

Console.Write("Содержимое стека stkl: "); while ( !stkl.IsEmpty()    )    {

ch = stkl.Pop ();

Console.Write(ch);

}

Console.WriteLine ();

Console.Write("Содержимое стека stk2: "); while ( !stk2.IsEmpty() )    {

ch = stk2.Pop ();

Console.Write(ch);

}

Console.WriteLine ("n");

}

}

Результат выполнения этой программы приведен ниже.

Поместить символы А-J в стек stkl.

Содержимое стека stkl: JIHGFEDCBA Содержимое стека stk2: JIHGFEDCBA

В классе StackDemo сначала конструируется первый стек (stkl), заполняемый символами. Затем этот стек используется, для конструирования второго стека (stk2). Это приводит к выполнению следующего конструктора класса Stack.

// Сконструировать объект класса Stack из существующего стека, public Stack(Stack ob) {

// Распределить память для стека, stck = new char[ob.stck.Length];

// Скопировать элементы в новый стек, for (int i=0; i < ob.tos; i++) stck[i] = ob.stck[i];

// Установить переменйую tos для нового стека, tos = ob.tos;

}

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

Вызов перегружаемого конструктора с помощью ключевого слова this

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

имя_конструктора{список_параметров1) : this (список_параметров2) {

II ... Тело конструктора, которое может быть пустым.

}

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

// Продемонстрировать вызов конструктора с помощью ключевого слова this.

using System;

class XYCoord { public int x, y;

public XYCoord()    :    this(0, 0)    {

Console.WriteLine("В конструкторе XYCoord()");

}

public XYCoord(XYCoord obj)    :    this(obj.x, obj.y) {

Console.WriteLine("В конструкторе XYCoord(obj)");

}

public XYCoord(int i, int j) {

Console.WriteLine("В конструкторе XYCoord(int, int)"); x = i;

У = j;

}

}

class OverloadConsDemo { static void Main()    {

XYCoord tl    =    new    XYCoord();

XYCoord t2    =    new    XYCoord(8,    9);

XYCoord t3    =    new    XYCoord(t2);

Console.WriteLine("tl.x,

tl.y:

" +

tl.x

+

" +

tl.y);

Console.WriteLine("t2.x,

t2. у:

" +

t2 .x

+ ",

" +

t2.y);

Console.WriteLine("t3.x,

t3.y:

" +

t3. x

+ ",

" +

t3.y);

}

}

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

В конструкторе XYCoord(int, int)

В конструкторе XYCoord()

В конструкторе XYCoord(int, int)

В конструкторе XYCoord(int, int)

В конструкторе XYCoord(obj)

tl.x, tl.y: 0, 0 t2 . x, t2 . у: 8, 9 t3.x, t3.у: 8, 9

Код в приведенном выше примере работает следующим образом. Единственным конструктором, фактически инициализирующим поля х и у в классе XYCoord, является конструктор XYCoord(int, int).А два других конструктора просто вызывают этот конструктор с помощью ключевого слова this. Например, когда создается объект

11, то вызывается его конструктор XYCoord (), что приводит к вызову this (0,    0),

который в данном случае преобразуется в вызов конструктора XYCoord (0, 0). То же самое происходит и при создании объекта t2.

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

public XYCoord(int х) : this(х, х) {    }

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

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*