Войти
ПрограммированиеФорумОбщее

Указатели на функции-члены классов (комментарии) (3 стр)

Страницы: 1 2 3 4 517 Следующая »
#30
22:31, 20 фев. 2013

=A=L=X=
> В С++ отсутствуют нормальные делегаты и указатели на функции не могут покрыть их функционал. В результате указатели на функции действительно не имеют мест для применения. Я по крайней мере тоже таковых не видел никогда.
Указатели на функции очень хорошо зарекомендовали себя для реализации коллбеков.
Но юзание указателей на методы класса - самый что ни на есть способ отстрелить себе ногу.


Если тебе нужен пул указателей на какие либо методы (как тут говорят, что бы избавиться от разбухшего switch) - юзай функциональное программирование. Не позволяет архитектура так сделать? Напиши функции-обертки, которые элементарно будут проверять класс на существование, синхронизировать блоки между потоками и т.п.


#31
22:36, 20 фев. 2013

По моему тема не раскрыта
указатели на функции объявляются так:

class _EngineShell_3D
{
    public:
    //....
    // можно изначально в классе объявить указатель на функцию
        unsigned int (*ClientGetDLLVersion)  (unsigned int *MainVersion,unsigned int *MainSubVersion,unsigned int *WorkVersion);
        unsigned int (*ClientGetEvent)    (int *InfoID, int *Result);
        unsigned int (*ClientGUIEvent)    (void);
        unsigned int (*ClientInit)      (_EngineShell_3D *p_SHELL_3D);
        unsigned int (*ClientRelease)    (void);
        unsigned int (*ClientRender)    (void);
}
// функцию саму можно загрузить из dll
ClientGetEvent=(unsigned int(*)(int *InfoID, int *Result))GetProcAddress(lc_ClientDLL,"ClientGetEvent");

> Есть в с++ одна интересная особенность: в этом языке не существует типа для результата
> работы функций (test.*pt). К нему можно только применить оператор вызова функции.
не правда. Просто не правильно обьявлен указатель на функцию

P.S. Считаю, что статьи должны быть статьями, а не пересказ одного пункта из учебника по С++

#32
23:17, 20 фев. 2013

KKH
> P.S. Считаю, что статьи должны быть статьями, а не пересказ одного пункта из
> учебника по С++
А, так это статья? Я-то думал, подсказка. О__о

#33
0:26, 21 фев. 2013

>Я-то думал, подсказка. О__о
eXmire, точно.

#34
8:10, 21 фев. 2013

Feo

Я поначалу когда говорил "указатель на функцию" имел ввиду "указатель на метод", потом исправился в более поздних постах.

#35
11:37, 21 фев. 2013

Эх.... нубы :)

Указатели на методы классов очень полезная штука. Вот как это применяется на самом деле:
http://code.google.com/p/et-engine/source/browse/trunk/include/et/app/events.h

        /*
        * Event 0
        */

        class Event0ConnectionBase : public EventConnectionBase
        {
        public:
                virtual void invoke() = 0;
                virtual void invokeInMainRunLoop(float delay) = 0;
        };

        template <typename RecevierType>
        class Event0Connection : public Event0ConnectionBase
        {
        public:
                Event0Connection(RecevierType* receiver, void(RecevierType::*func)());

                EventReceiver* receiver()
                        { return _receiver; }

                void invoke()
                        { (_receiver->*_receiverMethod)(); }

                void invokeInMainRunLoop(float delay = 0.0f)
                {
                        Invocation i;
                        i.setTarget(_receiver, _receiverMethod);
                        i.invokeInMainRunLoop(delay);
                }

        private:
                void (RecevierType::*_receiverMethod)();
                RecevierType* _receiver;
        };

        class Event0 : public Event, public Event0ConnectionBase
        {
        public:
                Event0();
                ~Event0();

                template <typename R>
                void connect(R* receiver, void (R::*receiverMethod)());
                void connect(Event0& e);

                template <typename R>
                void disconnect(R* receiver);

                void receiverDisconnected(EventReceiver* r);
                void invoke();
                void invokeInMainRunLoop(float delay = 0.0f);

        private:
                EventReceiver* receiver() 
                        { return 0; }

                void cleanup();

        private:
                typedef std::vector<Event0ConnectionBase*> ConnectionList;
                ConnectionList _connections; 
                bool _invoking;
        };

Используется так:

Event0 e;
e.connect(this, &MyObject::doSmthng);
e.connect(otherObj; &OtherClass::doOther);

e.invoke();

Концепция сигналов и слотов постороена на этой технике. Так что если вы не одобряете это только потому, что не знаете этому применения - вынужден не согласиться.

#36
12:44, 21 фев. 2013

Sergio

Причём самое интересное - были бы нормальные делегаты (как __delegate в C++Builder) оное же реализовывалось бы десятью строчками (в сущности пляски с контейнером просто) причём без шаблонных техник и потому без лишних динамических аллокаций инвоукеров.

#37
12:52, 21 фев. 2013

Ну оступился в начале пути Страуструп. Вместо делегатов придумал неуклюжие указатели на методы, которые без плясок с шаблонами и динамической аллокацией нельзя выделить в расширяемый тип кэллбэков. Поэтому std::function тормозит не по детски при инициализации, т.к. лезет в хип. Ну я понял бы что это было так давно что еще не совсем понятно тогда было как правильно сделать кэллбэки у объектов. Но после того как в C++11 на этот момент всё так же положили жирный болт - вот тут я негодую.

#38
14:55, 21 фев. 2013

=A=L=X=
> В С++ отсутствуют нормальные делегаты и указатели на функции не могут покрыть
> их функционал. В результате указатели на функции действительно не имеют мест
> для применения. Я по крайней мере тоже таковых не видел никогда.

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


Указатели на функции/методы столько же сырой низкоуровневый материал, как и просто сырые указатели.
Они находят широкое применение в библиотечных инструментальных классах (те же делегаты), но использовать их в высокоуровневом коде - это почти так же глупо как и обычные сырые указатели. Просто менее удобно. И соответственно, среднестатистический программист реже прибегает к подобным возможностям языка.


=A=L=X=
> Поэтому еще раз: указатели на методы не нужны, нужны делегаты.
Реализация которых чуть меньше чем полностью основана на низкоуровневой работе с указателями.

С таким же успехом можно сказать: char* text не нужен. Нужен std::string!

И тебе ничто не мешает  изготовить для себя делегат, и работать с ним. Если тебе не хочется самому изобретать велосипед - есть же уже масса готовых реализаций.
Что-то в 11 стандарт даже вошло.

#39
14:56, 21 фев. 2013

Sergio
> Эх.... нубы :)
> Указатели на методы классов очень полезная штука.
не оспаривая (по/беспо)лезность указателей на методы класса, хочу напомнить о http://en.wikipedia.org/wiki/Double_dispatch прекрасно решающем проблемы затронутые в топиге 

#40
15:21, 21 фев. 2013

эм... а std::function ещё никто не советовал?

#41
15:57, 21 фев. 2013

Chaos_Optima
> эм... а std::function ещё никто не советовал?

Он какой то недоделанный.

Во-первых он нарушает принцип "единственного типа данных", что делает работу с ним неудобной. Поскольку конкретные инстансы шаблона - это разные типы.
Во-вторых, используя его постоянно приходится иметь дело с шаблоно-кодом, что увеличивает сложность не очень красивого кода.

А в третьих, лично меня очень сильно смущает реализация механизма, которая она ну просто изобилует конструкциями вида:

 // Handle objects
      _Res
      operator()(_Class& __object, _ArgTypes... __args) const
      { return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); }


У вариардиков есть одна особенность - вывод типа из аргумента будет по значению, а не по ссылкам, что приведет к вызовам копирующий конструкторов.

На самом деле, я серьёзно никогда не занимался исследованием этого механизма. Могу предположить, что std::function не использует вывод прототипа функции напрямую из цели, а использует явно вызываемые программистом типы (что не есть удобно для самого программиста, но безопасно для производительности)

Лично я предпочитаю использовать свой удобный и быстрый коннектор.
Но если бы захотел использовать std::function, то я бы хотел быть уверенным, что вариардики не просадят мне производительность на тяжелых объектах.

#42
16:33, 21 фев. 2013

Передача по значению во многих случаях очень хорошо оптимизируется.

#43
16:39, 21 фев. 2013

В std::function напрягает только обращение к куче.
Абстрагироваться от сигнатуры функции можно, но либо свой RTTI либо dynamic_cast надо использовать, что не есть хорошо.

#44
16:56, 21 фев. 2013
class Test
{
  public:
    Test() : f(&Test::f0), f0(&Test::f1), f1( &Test::f2 ) {}
    float (  Test::* const Test::* const Test::* const f)();
  private:
    float ( Test::* const Test::* const f0)();
    float ( Test::* const f1)() ;
    float f2() { return 0; }
};

...
Test t;
cout << (t.*(t.*(t.*(t.f))))();
...
@При копирование сохранять авторство.

указатель на метод можно использовать как локальная стат машина, или как стротегия когда алгоритму передается ссылка на метод которым пользоватся.

Страницы: 1 2 3 4 517 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.