Александр Шаргин Делегаты на C++

Введение

Делегаты - это объектно-ориентированные указатели на функции, используемые для callback-вызовов в среде CLR фирмы Microsoft. Делегат можно связать со статической функцией или с нестатическим методом любого класса (единственное условие - совпадение сигнатуры метода с сигнатурой, указанной в описании делегата). Затем связанную с делегатом функцию или метод можно вызывать, используя стандартный синтаксис вызова функции в C++. Несколько делегатов можно связать в цепочку. Благодаря этому можно "одним махом" вызвать все связанные с ними callback-функции. Следующий пример демонстрирует применение делегатов в языке C#.

using System; 

using System.IO; 


namespace CSharpDelegates {

 class App {

  // Определяем делегат Callback, 

  // который принимает 1 параметр и ничего не возвращает. 

  public delegate void Callback(string str); 


  // Это метод класса App. 

  public void OutputToConsole(string str) {

  Console.WriteLine(str);

  } 


  // А это статический метод класса App. 

  public static void OutputToFile(string str) {

  StreamWriter sw = new StreamWriter("output.txt", true); 

  sw.WriteLine(str); 

  sw.Close();

  } 


  public static void Main(string[] args) {

  App app = new App(); 


  // Создаём делегат. 

  App.Callback callback = null; 

  if (callback != null) callback("1"); 


  // Добавляем ссылку на OutputToFile. 

  // Вызываем её через делегата. 

  callback += new App.Callback(App.OutputToFile);

   if (callback != null) callback("2");


  // Добавляем ссылку на OutputToConsole.

   // Вызывается вся цепочка:

   // сначала OutputToFile, потом OutputToConsole.

   callback += new App.Callback(app.OutputToConsole);

   if (callback != null) callback("3");


   // Убираем ссылку на OutputToFile.

   // Вызывается только OutputToConsole.

   callback -= new App.Callback(App.OutputToFile);

   if (callback!= null) callback("4");


   // Убираем оставшуюся ссылку на OutputToConsole.

   callback -= new App.Callback(app.OutputToConsole);

   if (callback != null) callback("5");

  }

 }

} 


Делегаты в CLR удобны, типобезопасны и эффективны. Последнее время на форумах RSDN часто поднимается вопрос о том, можно ли реализовать делегаты с аналогичными свойствами, оставаясь в рамках "чистого" C++. Оказывается, это вполне возможно. В этой статье я покажу, как это сделать.

Загрузка...