Главная arrow Язык программирования C# arrow C# Полное руководство Герберт Шилдт arrow Перегрузка конструкторов C# Полное руководство Герберт Шилдт

Перегрузка конструкторов C# Полное руководство Герберт Шилдт

Как и методы, конструкторы также могут перегружаться. Это дает возможность конструировать объекты самыми разными способами. В качестве примера рассмотрим следующую программу:

// Продемонстрировать перегрузку конструктора.

using System;

class MyClass {
   public int x;
   
   public MyClass() {Console .WriteLine ("В конструкторе MyClass ().") ;
      x = 0;
   }

   public MyClass(int i) {
      Console.WriteLine(
                                  "В конструкторе MyClass(int).");
      x = i;
   }

   public MyClass(double d) {
      Console .WriteLine ("В конструкторе MyClass (double) .") ;
      x = (int) d;
   }

   public MyClass (int i, int j) {
      Console .WriteLine ("В конструкторе MyClass(int, int).");
      x = i * j;

class OverloadConsDemo {
   static void Main() {
      MyClass t1 = new MyClass();
      MyClass t2 = new MyClass(88);
      MyClass t3 = new MyClass(17.23);
      MyClass t4 = new MyClass (2, 4);

      Console.WriteLine("t1 .x: " + t1.x);
      Console.WriteLine("t2.x: " + t2.x);
      Console.WriteLine("t3.x: " + t3.x);
      Console.WriteLine("t4.x: " + t4.x);
   }
}

При выполнении этой программы получается следующий результат:
   В конструкторе MyClass ().
   В конструкторе MyClass(int).
   В конструкторе MyClass(double).
   В конструкторе MyClass(int, int).
   t1.x: 0
   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 IsFull () {
   return tos==stck.Length;
}

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

// Возвратить общую емкость стека.
public int Capacity () {
   return stck.Length;
}

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

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

class StackDemo {
   static void Main() {
      Stack stk1 = new Stack (10);
      char ch;
      int i;

      // Поместить ряд символов в стек stk1.
      Console.WriteLine("Поместить символы А-J в стек stk1.");
      for(i=0; !stk1.IsFull(); i++)
         stk1.Push((char) ('A' + i) ) ;

      // Создать копию стека stck1.
      Stack stk2 = new Stack (stk1);

      // Вывести содержимое стека stk1.
      Console.Write("Содержимое стека stk1: ");
      while ( !stk1.IsEmpty() ) {
         ch = stk1.Pop();
         Console.Write(ch);
      }

      Console.WriteLine();

      Console.Write("Содержимое стека stk2: ");
      while ( !stk2.IsEmpty() ) {
         ch = stk2 . Pop () ;
         Console.Write(ch);
      }
      Console.WriteLine("\n");
   }
}


Результат выполнения этой программы приведен ниже.
   Поместить символы А-J в стек stk1.
   Содержимое стека stk1: JIHGFEDCBA
   Содержимое стека stk2: JIHGFEDCBA

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

// Сконструировать объект класса Stack из
// существующего стека.
public Stack(Stack ob) {
   // Распределить память memory для стека.
   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, содержащая индекс вершины стека. По завершении работы конструктора новый и исходный стеки существуют как отдельные, хотя и одинаковые объекты.