Re: Идея механизма событий библеотеки виджетов GUI
От: Кывт Ниоткуда  
Дата: 08.03.09 18:34
Оценка: 6 (1)
Насколько я понял, идея бесперспективна.

1. В такой реализации, которую ты привел, она вообще бесполезна, так как обработчик события — один на весь класс и не имеет доступа к экземпляру класса. Если расширить ее до того, чтобы она поддерживала экземпляры классов, то идея должна как-то измениться. Как ты собираешься передавать экземпляры? Мне ведь нужно подписать конкретный обработчик на событие конкретной кнопки, а не всех кнопок в программе.

Приведи пример, как с помощью твоей идеи (уже в расширенном виде) я могу решить следующую задачу:

class Button : public Widget
{
public:

    Event<ClickedEvent> Clicked;  
};

class MyForm : public Form
{
public:

    MyForm()
    {
        button1.Clicked += ClickedEventHandler(*this, &MyForm::OnButton1Clicked);
        button2.Clicked += ClickedEventHandler(*this, &MyForm::OnButton2Clicked);
    }

private:

    Button button1;
    Button button2;

private:

    void OnButton1Clicked(Point location)
    {
        // Has to be called when button1 is clicked.
    }

    void OnButton2Clicked(Point location)
    {
        // Has to be called when button2 is clicked.
    }
};


2. А как передавать параметры? Все сообщения не могут быть без параметров.

3. Целочисленные идентификаторы сообщений. Что делать с идентификаторами сообщений при наследовании? Допустим, в базовом классе использованы идентификаторы с нуля по 5, в производном классе, значит, мы должны использовать идентификаторы начиная с 6? Да? Надо как-то это обеспечить, и сделать так, чтобы никто про это не забыл. Хорошо, а если мы решили ввести дополнительное сообщение в базовый класс? А множественное наследование? Даже если это и получится, это будет в любом случае уродливо и ненадежно.

4. При полноценной реализации эффективность окажется плохой. Сколько в интерфейсе приложения может быть объектов, произведенных от класса Widget? Десятки тысяч. Сколько в них может быть задействовано обработчиков сообщений? Сотни тысяч. При этом тебе нужно будет создать маппинг для каждого обработчика. Таким образом, каждый вызов каждого обработчика будет вызывать поиск по внушительному индексу. Насколько это замедлит быстродействие, трудно предсказать.

5. Если у тебя Event имеет хоть какие-то данные, то, в любом случае — объявлять его одной строчкой некошерно. Потому что это получаются открытые данные класса.

На самом деле, проблема-то серьезная. Похоже, что и особо хорошего решения для нее не существует — у всех есть свои недостатки.

В MFC — страшные макросы.
В QT — (короткие и простые) макросы + дополнительный препроцессор.

Я такую проблему решил с помощью делегатов на C++. Перед решением изучил изыскания Дона Клагстона. Я взял только общую идею, но реализовал гораздо проще. Внешне получилось точно как в дотнете.

Но когда реализовал, сразу понял, в чем недостаток: если сделать много event'ов, получается много неиспользуемой памяти. Допустим, неиспользованный event использует четыре байта памяти (место под указатель). У меня в контроле 33 event'а, из них используются 3. Неиспользуемой памяти 30 x 4 = 120 байт на каждый контрол. Допустим, в диалоге 3000 контролов — получаем 3000 x 120 = ~360 кбайт совершенно впустую.

Теперь думаю про другой подход. На самом деле, в итоге некий подход, подобный твоему, наверно, и будет оптимальным, только не в таком виде.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.