Виртуальные функции в C#

Лекции по предмету «Программирование»
Информация о работе
  • Тема: Виртуальные функции в C#
  • Количество скачиваний: 12
  • Тип: Лекции
  • Предмет: Программирование
  • Количество страниц: 6
  • Язык работы: Русский язык
  • Дата загрузки: 2015-01-04 00:07:03
  • Размер файла: 42.74 кб
Помогла работа? Поделись ссылкой
Информация о документе

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

Если Вы являетесь автором текста представленного на данной странице и не хотите чтобы он был размешён на нашем сайте напишите об этом перейдя по ссылке: «Правообладателям»

Можно ли скачать документ с работой

Да, скачать документ можно бесплатно, без регистрации перейдя по ссылке:

Виртуальные функции в C#

Когда класс желает изменить реализацию деталей виртуального метода, он делает это с помощью ключевого слова override. Если базовый класс желает определить метод, который может бъипь (но не обязательно) переопределен в подклассе, он должен пометить его ключевым словом virtual: Троелсен стр.241-243 Если набрать слово override внутри контекста типа класса (и нажать клавишу пробела), то система автодополнения автоматически отобразит список всех переопределяемых членов родительского класса,
Виртуальная функция определяется внутри базового класса и может быть переопределена в производном классе. Ключевое слово virtual указывает на виртуальную функцию, например:
public virtual void fun ( )
{
// Операторы реализации функции
}
Поскольку виртуальная функция переопределяется в производном классе, то это напоминает перегрузку функций. Различие заключается в том, что при перегрузке функций различны списки параметров, а в виртуальных функциях количество и типы аргументов должны строго совпадать, различны только алгоритмы.
Ниже приведена программа, состоящая из базового и двух производных классов. В задаче определяется сопротивление цепи, состоящей из двух резисторов. Резисторы могут быть соединены последовательно или параллельно. При последовательном соединении сопротивления суммируются, при параллельном соединении суммируются проводимости:

Разобраться R → res

Для двух резисторов общее сопротивление равно произведению исходных сопротивлений, которое делится на их сумму.
class Res // Базовый класс
{
protected double res1, res2; // Сопротивления
public Res() { res1 = res2 = 0.0; } // Конструктор без параметров
public virtual double get_chain_resist()
{
return 0.0; // Эта функция должна что-нибудь возвращать
}
// Свойство для первого резистора
public double R1
{
get { return res1; }
set { res1 = value; }
}
// Свойство для второго резистора
public double R2
{
get { return res2; }
set { res2 = value; }
}
}
// Этот класс определяет сопротивление цепи при параллельном
// соединении резисторов */
class Paral : Res
{
// Конструктор принимает 2 параметра и передает их в конструктор
// с параметрами базового класса
public Paral(double r1, double r2): base()
{
this.res1 = r1;
this.res2 = r2;
}
public override double get_chain_resist()
{
return R1*R2/(R1 + R2);
}
}
// Этот класс определяет сопротивление цепи при
// последовательном соединении резисторов
class Sequent : Res
{
// Конструктор c двумя параметрами и наследник пустого
// конструктора базового класса
public Sequent(double r1, double r2) : base()//
{
this.res1 = r1;
this.res2 = r2;
}
public override double get_chain_resist()
{
return R1 + R2; // Итоговое сопротивление
}
}
class Program
{
static void Main(string[] args)
{
double inr1, inr2;
Console.WriteLine("
Введите значения сопротивлений
");
inr1 = double.Parse(Console.ReadLine());
inr2 = double.Parse(Console.ReadLine());
//Объявление базового класса
Res r = new Res ();
// Объявление производного класса для последовательного соединения
r = new Sequent(inr1, inr2);
Console.WriteLine(" R при последовательном соединении = " +
r.get_chain_resist());
// Объявление производного класса для параллельного соединения
r = new Paral(inr1, inr2);
Console.WriteLine(" R при параллельном соединении = " +
r.get_chain_resist());
Console.ReadKey(); // Для останова экрана пользователя
}
}
Пример выполнения программы:

В приведенном выше примере виртуальная функция базового класса не имеет выполняемых действий. Полезные операции она выполняет только после переопределения в производных классах. Это распространенная ситуация, при которой базовый класс содержит только набор пустых функций, которые должны переопределяться в производных классах.
У одного базового класса может быть несколько производных классов. В каждом из таких классов виртуальная функция, указанная в базовом классе, может переопределяться по-разному. Ссылка на базовый класс можно использовать для обращения к членам производных классов, а это позволяет иметь одинаковый интерфейс для выполнения разных действий с объектом. Этот принцип называется полиморфизмом.
Для иллюстрации сказанного в приведенной выше программе для получения значений сопротивлений для разных видов соединения применяется одна и та же форма вызова:
r.get_chain_resist(), где r объект базового класса.
Если виртуальная функция в базовом классе не выполняет никаких действий, ее можно объявить абстрактной, чтобы подчеркнуть, что она пустая. Для приведенного выше примера объявление будет иметь вид:
public abstract double get_chain_resist();
Если класс имеет хотя бы одну виртуальную функцию, то он называется абстрактным.
Ниже приведена программа из книги Г. Шилдта «Полный справочник по языку C#», в которой рассматривается несколько производных классов. Для этой программе выполнена косметическая правка
class TwoDShape
{
double pri_width;
double pri_height;
public TwoDShape() // Конструктор по умолчанию,
{
Width = Height = 0.0; // параметры конструктора определены в свойствах
name = "null";
}
// Конструктор с параметрами.
public TwoDShape(double w, double h, string n)
{
Width = w;
Height = h; name = n;
}
// Конструктор объекта с одинаковой шириной и высотой.
public TwoDShape(double x, string n)
{
Width = Height = x;
name = n;
}
// Конструктор копирования для объекта TwoDShape.
public TwoDShape(TwoDShape ob)
{
Width = ob.Width;
Height = ob.Height;
name = ob.name;
}
// Свойства ширины и высоты объекта,
public double Width
{
get { return pri_width; }
set { pri_width = value < 0 ? -value : value; }
}
public double Height
{
get { return pri_height; }
set { pri_height = value < 0 ? -value : value; }
}
public string name { get; set; } // Свойство для названия
public void ShowDim()
{
Console.WriteLine("Ширина и высота равны "+Width + " и " + Height);
}
public virtual double Area()
{
return 0.0;
}
}
// Класс для треугольников, производный от класса TwoDShape.
class Triangle : Two Shape
{
string Style;
public Triangle() // Конструктор, используемый по умолчанию,
{
Style = "null";
}
// Конструктор для класса Triangle,
public Triangle(string s, double w, double h) : base(w, h, "треугольник")
{
Style = s;
}
// Конструктор для равнобедренного треугольника,
public Triangle(double x) : base(x, "треугольник")
{
Style = "равнобедренный";
}
// Конструктор копирования для объекта типа Triangle,
public Triangle(Triangle ob) : base(ob)
{
Style = ob.Style;
}
// Переопределить метод Area() для класса Triangle,
public override double Area() { return Width * Height / 2; }
public void ShowStyle() // Показать тип треугольника
{
Console.WriteLine("Треугольник " + Style);
}
}
//Класс для прямоугольников, производный от класса TwoDShape.
class Rectangle : TwoDShape
{
// Конструктор для класса Rectangle,
public Rectangle(double w, double h) : base(w, h, "прямоугольник") { }
// Конструктор для квадрата
public Rectangle(double x) : base(x, "прямоугольник") { }
// Конструктор копирования объекта типа Rectangle,
public Rectangle(Rectangle ob) : base(ob) { }
// Возвратить логическое значение true, если квадрат.
public bool IsSquare()
{
if (Width == Height) return true;
return false;
}
// Переопределить метод Area() для класса Rectangle,
public override double Area()
{
return Width * Height;
}
}
class DynShapes
{
static void Main()
{
TwoDShape[] shapes = new TwoDShape[5];
shapes[0] = new Triangle("прямоугольный", 8.0, 12.0);
shapes[1] = new Rectangle(10);
shapes[2] = new Rectangle(10, 4);
shapes[3] = new Triangle(7.0);
shapes[4] = new TwoDShape(10, 20, "общая форма");
for (int i = 0; i < shapes.Length; i++)
{
Console.WriteLine("Объект — " + shapes[i].name);
Console.WriteLine("Площадь равна " + shapes[i].Area());
Console.WriteLine();
}
Console.ReadKey();
}
}
Обратите внимание на вызов разных конструкторов. Ниже приведен пример вывода.