Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Медведев_С++_CLI_C#_Java_J#.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆

Пример 8.2.2. Использование делегата как параметра функции.

////////////////////

// C++/CLI

#include "stdafx.h"

using namespace System;

delegate void del (void); // Объявление делегата del

ref class CA

{

// Класс с функцией R() для делегата del

public:

Void r(void) {Console::WriteLine ("r");}

};

void M (del ^d) {d();} // Глобальная функция для делегата del

Void main () // Главная функция программы

{

CA ^pCA= gcnew CA ( ); // Создать объект класса CA

del ^pDel; // Ссылка на объект делегата del

pDel= gcnew del (pCA, &CA::R); // Создать объект делегата

M(pDel); // Функция M() вызовет функцию CA::R

Console::ReadKey();

}

////////////////////

// C#

using System;

using System.Collections.Generic;

using System.Text;

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

delegate void del(); // Объявление делегата del

class CA

{

// Класс с функцией R() для делегата del

public void R() {Console.WriteLine ("R");}

};

class Program

{

static void M (del d) {d();} // Статическая функция для делегата del

static void main() // Главная функция программы

{

CA a = new CA ( ); // Создать объект класса CA

del deleg; // Ссылка на объект делегата del

deleg= new del (a.R); // Создать объект делегата

M(deleg); // Функция M() вызовет функцию CA::R

Console.ReadKey();

}

}

////////////////////

// Java и J#

class del // Объявление "делегата" del

{

public void R() {System.out.println ("R");}

}

public class Test

{

// Статическая функция для делегата del

static void M (del d) {d.R();}

public static void main(String[] args)

{

del d= new del(); // Создать делегирующий объект d класса del

M(d); /* Выполнить функцию, инкапсулированную в объекте d

"делегата" (класса del) */

}

}

C#. В примере 8.2.2 использовано пространство имён System для доступа к консольному классу и классу делегата. Вначале объявляется делегат del

delegate void del ();

для функций формата

Void имя-функции ( void );

В классе CA описана обычная функция R() для делегирования делегатом del.

Основной класс CA кроме описания главной статической функции Main() включает описания статической функций M(), параметром которой является делегат del. Выполнение этой функции M() состоит в вызове делегированной функции R().

Перед использованием делегата главная функция Main() создаёт его объект. Для инкапсулирования обьгчной функции R() класса CA пришлось создать объект а этого класса, и применить ссылку а при создании объекта делегата.

CA a= new CA ();

del deleg= new del (a.R);

Объект deleg делегата передаётся в качестве аргумента в статическую функцию M().

M (deleg);

C++/CLI. Программа на языке C++/CLI схожа с программой на языке C#. Но здесь применяется управляемый класс, дескрипторы, оператор gcnew.

Язык C++/CLI включает ключевое слово delegate управляемого расширения. Встретив delegate, компилятор создаёт управляемый класс делегата.

Функция Main() создаёт объект pCA класса CA в управляемой куче

CA ^pCA= gcnew CA ( ); // Создать объект класса, содержащий функцию R()

Потом создаётся объект pDel делегата del

del ^pDel= gcnew del (pCA, &CA::R); // Создать объект делегата

// для обычной функции R()

Этот делегат передаётся статической функции M().

J# и Java. Делегирование впервые было введено в языке Java и используется при обработке событий и уведомлений, но позднее создатели языка C# выделили делегат как специальный класс Delegate, существенно упростив его описание с помощью ключевого слова delegate. С помощью объектов делегата значительно упрощается применение функций в языках C# и C++/CLI, о чём свидетельствуют примеры 8.2.1, 8.2.2. И, как в дальнейшем мы увидим, использование делегатов существенно облегчает создание и применение событий в языках C# и C++/CLI, вносит единообразие и простоту.

Если появится необходимость выполнить некоторую функцию в теле другой функции, то в языках Java и J++ приходится создать свой специальный класс, подменив им класс делегата языков C# и C++/CLI и поместив в этот класс подлежащую выполнение функцию, а затем объект этого класса, как объект делегата, передать в качестве аргумента, например, так, как в примере 8.2.2.

8.3События языков C++/CLI и C#

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

При нажатии на клавишу происходит (генерируется) событие (event) и на него среагирует специальная функция - обработчик (event handler) этого события, выполнив надлежащее действие. Событие и его обработчик могут локализоваться в одном приложении, но могут принадлежать разным приложениям или разным компьютерам, то есть быть отдалёнными (remoting).

Напрашивается мысль о схожести между событием и делегатом, между делегируемой функцией и обработчиком. Сравним событие с делегатом. Выполняется событие (вызывается одиночный объект делегата) и соответствующий обработчик реагирует на событие (выполняется делегируемая объектом делегата функция). Выполняется событие (вызывается множественный объект делегата) и соответствующие обработчики реагируют на событие (выполнятся функции, инкапсулированные в добавленных объектах делегата к множественному объекту делегата). Как много схожего. И действительно, событие является частным случаем делегата. А чем отличается событие от делегата, видно из примера 8.3.1. Просмотрите его внимательно, убедитесь, что слово event существенно изменило употребление делегата-события. Превращённый в объект-событие объект-делегата можно вызвать только внутри объекта класса, в котором этот делегат-событие объявлен. Волшебное слово event заставляет компилятор внести в код нечто, что делает событие отличным от делегата.