Форум программистов, компьютерный форум CyberForum.ru

c++ делегирование ( c++ delegate pattern) - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
noname_club
 Аватар для noname_club
100 / 88 / 9
Регистрация: 01.05.2013
Сообщений: 563
11.09.2013, 16:25     c++ делегирование ( c++ delegate pattern) #1
развеем туман над таким паттерном как делегирование

итак сначала отправимся на WIKI и просмотрим что нам предлается в качестве примера

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
 
class I {
   public:
      virtual void f() = 0;
      virtual void g() = 0;
};
 
class A : public I {
   public:
      void f() { std::cout << "A: вызываем метод f()" << std::endl; }
      void g() { std::cout << "A: вызываем метод g()" << std::endl; }
};
 
class B : public I {
   public:
      void f() { std::cout << "B: вызываем метод f()" << std::endl; }
      void g() { std::cout << "B: вызываем метод g()" << std::endl; }
};
 
class C : public I {
   public:
     // Конструктор
      C() : m_i ( new A() ) { }
     // Деструктор
      virtual ~C() {
         delete m_i;
      }
      void f() { m_i->f(); }
      void g() { m_i->g(); }
     // Этими методами меняем поле-объект, чьи методы будем делегировать
      void toA() {
         delete m_i;
         m_i = new A();
      }
      void toB() {
         delete m_i;
         m_i = new B();
      }
   private:
     // Объявляем объект методы которого будем делегировать
      I * m_i;
};
 
int main() {
   C c;
 
   c.f();
   c.g();
   c.toB();
   c.f();
   c.g();
 
   return 0;
}
 
/* Output:
A: вызываем метод f()
A: вызываем метод g()
B: вызываем метод f()
B: вызываем метод g()
*/
есди кратко, то предлается использовать абстрактный класс в качестве интерфейса.

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

--

Предлагаю еще один метод делегирования, который предполагает отсуствие интерфейса
таким образом важным становится какие именно аргументы переданы в метод, а не имя метода

пример:
test_selectors.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef __c___console__test_selectors__
#define __c___console__test_selectors__
 
#include <iostream>
 
using namespace std;
 
class abstractObject {
public:
    int tag;
};
 
//
 
typedef void (abstractObject::*SELECTOR_HANDLER1) (abstractObject*); // baseclass param
typedef void (abstractObject::*SELECTOR_HANDLER2) (int);            // int param
typedef void (abstractObject::*SELECTOR_HANDLER3) (const char*, const char*); // two simple string params
 
//
 
class realObject : public abstractObject {
public:
    void method1(abstractObject* obj);
    void method1v1(abstractObject* obj);
    void method1v2(abstractObject* obj);
    void method2(int intvalue);
    void method3(const char* str1, const char* str2);
};
 
#endif /* defined(__c___console__test_selectors__) */

сразу можно заметить что я объвил через typedef будующие "шаблоны" функций с аргументами, которые будут вызывать посредством делегирования

также объявлен класс realObject наследник пустого класса abstractObject

необходимость в abstractObject обусловлена шаблонами функций в typedef

код методов класса realObject:

test_selectors.cpp

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "test_selectors.h"
 
using namespace std;
 
void realObject::method1(abstractObject *obj) {
    cout << "realObject" << tag << "::method1 called with obj.tag = " << obj->tag << endl;
}
 
void realObject::method1v1(abstractObject *obj) {
    cout << "realObject" << tag << "::method1v1 called with obj.tag = " << obj->tag << endl;
}
 
void realObject::method1v2(abstractObject *obj) {
    cout << "realObject" << tag << "::method1v2 called with obj.tag = " << obj->tag << endl;
}
 
void realObject::method2(int intvalue) {
    cout << "realObject" << tag << "::method2 called int = " << intvalue << endl;
}
 
void realObject::method3(const char *str1, const char *str2) {
    cout << "realObject" << tag << "::method3 called str1 = " << str1 << " str2 = " << str2 << endl;
}
код программы

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
 
#include "test_selectors.h"
 
// демонстрация вызова функций по ссылке, прототип паттерна "делегирование"
 
void call_handler1(abstractObject*target, SELECTOR_HANDLER1 handler1, abstractObject*objvalue) {
    
    (target->*handler1) (objvalue);
}
 
void call_handler2(abstractObject*target, SELECTOR_HANDLER2 handler2, int value) {
    
    (target->*handler2) (value);
}
void call_handler3(abstractObject*target, SELECTOR_HANDLER3 handler3, const char *str1, const char *str2) {
    
    (target->*handler3) (str1, str2);
}
    
 
 
int main(int argc, const char * argv[])
{
    
    realObject *myobject = new realObject;
    
    realObject *testobject = new realObject;
    
    testobject->tag = 111;
    myobject->tag = 222;
    
    // вызываем методы вручную
    
    myobject->method1(testobject);
    myobject->method2(333);
    myobject->method3("hello", "world");
    
    // вызываем методы по ссылке
    
    cout << "----------" << endl;
    
    call_handler1(myobject, (SELECTOR_HANDLER1) &realObject::method1 , testobject);
    call_handler1(myobject, (SELECTOR_HANDLER1) &realObject::method1v1 , testobject);
    call_handler1(myobject, (SELECTOR_HANDLER1) &realObject::method1v2 , testobject);
    
    call_handler2(myobject, (SELECTOR_HANDLER2) &realObject::method2 , 707);
    
    call_handler3(myobject, (SELECTOR_HANDLER3) &realObject::method3 , "apple", "world");
    
    // вызываем методы по ссылке у объекта testobject
    
    cout << "----------" << endl;
    
    call_handler1(testobject, (SELECTOR_HANDLER1) &realObject::method1 , testobject);
    
    call_handler2(testobject, (SELECTOR_HANDLER2) &realObject::method2 , 707);
    
    call_handler3(testobject, (SELECTOR_HANDLER3) &realObject::method3 , "apple", "world");
 
    return 0;
}
ответ консоли
realObject222::method1 called with obj.tag = 111
realObject222::method2 called int = 333
realObject222::method3 called str1 = hello str2 = world
----------
realObject222::method1 called with obj.tag = 111
realObject222::method1v1 called with obj.tag = 111
realObject222::method1v2 called with obj.tag = 111
realObject222::method2 called int = 707
realObject222::method3 called str1 = apple str2 = world
----------
realObject111::method1 called with obj.tag = 111
realObject111::method2 called int = 707
realObject111::method3 called str1 = apple str2 = world
функции call_handler1, call_handler2, call_handler3 наглядно показывают каким образом вызывать переданный по ссылке метод с параметрами

методы

realObject::method1
realObject::method1v1
realObject::method1v2


имеют одинаковую структуру аргументов, но разные имена

если бы использовался интерфейс то пришлось бы их опысывать в нем.

C++
1
2
3
4
5
call_handler1(myobject, (SELECTOR_HANDLER1) &realObject::method1 , testobject);
call_handler1(myobject, (SELECTOR_HANDLER1) &realObject::method1v1 , testobject);
call_handler1(myobject, (SELECTOR_HANDLER1) &realObject::method1v2 , testobject);
 
// не требуется описывать интерфейс чтобы вызвать существующий метод класса
----

PS

данный способ делегирования используется в Cocos2dX с++

только там там все красиво спрятано за макросами
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.09.2013, 16:25     c++ делегирование ( c++ delegate pattern)
Посмотрите здесь:

Template Method Pattern C++
Делегирование C#
C++ strategy pattern
Делегирование C++
.RAW to JPEG with Bayer Pattern C++
C++ Template Method Pattern
Делегирование Objective-C
Делегирование

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать тему
Опции темы

Текущее время: 02:32. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru