Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 08:16
Оценка:
Привет всем!

Помогите по поводу sabj.

У меня есть класс CTimer потомок от CObject (реализация заимствована из VCL ) в нем объявлена переменная m_OnTimer...

    private:
         ...

        TNotifyEvent    m_OnTimer;

        ...


...где TNotifyEvent...


    typedef void (CObject::* TNotifyEvent)(CObject* Sender);


Задача проста, мне нужно вызвать функцию котораю будет присвоена m_OnTimer. Вот как я это делаю...

    void CTimer::Timer(void)
    {
        if ( m_OnTimer != NULL )
            (this->*m_OnTimer)(this);
    };


Но чтото мне подсказывает, что вот так (this->*m_OnTimer)(this); не совсем правильно, али как подскажите плиз...
-= The Alien//Ufocomp =-
Re: Как вызвать переменную объявленную как функция?
От: SergeantAlexx  
Дата: 16.06.03 09:04
Оценка: -1
Здравствуйте, alienufo, Вы писали:

A>
A>    typedef void (CObject::* TNotifyEvent)(CObject* Sender);
A>


A> Но чтото мне подсказывает, что вот так (this->*m_OnTimer)(this); не совсем правильно, али как подскажите плиз...


По-моему, лучше будет m_OnTimer(this)

Удалено избыточное цитирование. -- ПК.
Re[2]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 09:23
Оценка:
Здравствуйте, SergeantAlexx, Вы писали:

SA>По-моему, лучше будет m_OnTimer(this)


не все так просто...

error C2064: term does not evaluate to a function
-= The Alien//Ufocomp =-
Re[3]: Как вызвать переменную объявленную как функция?
От: SeriousSam Россия null
Дата: 16.06.03 11:01
Оценка: -1
Здравствуйте, alienufo, Вы писали:

A>Здравствуйте, SergeantAlexx, Вы писали:




SA>>По-моему, лучше будет m_OnTimer(this)




A>не все так просто...




A>error C2064: term does not evaluate to a function




Try this:

(*(m_OnTimer))(this);
Re[3]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 11:31
Оценка: 2 (1)
А ты не слушай вредных советов.
Указатель на член это не тоже самое, что указатель на функцию.

Вызывают с таким синтаксисом
(obj.*pf)(params);
(p_obj->*pf)(params);
Of course, the code must be complete enough to compile and link.
Re[4]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 11:36
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Вызывают с таким синтаксисом

L_L>
L_L>(obj.*pf)(params);
L_L>(p_obj->*pf)(params);
L_L>


Но тут возникает другие проблемы если не трудно то пролистай до конца http://www.rsdn.ru/Forum/Message.aspx?mid=297222&only=1
Автор: alienufo
Дата: 16.06.03
-= The Alien//Ufocomp =-
Re[5]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 11:49
Оценка:
Что это?
Как это?


Что такое вот это

m_Timer.OnTimer = (TNotifyEvent) OnTimer;?
Of course, the code must be complete enough to compile and link.
Re[5]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 12:01
Оценка:
Вникать во все это неохота. Но, сдается мне, что ты хочешь чтоб для объекта m_timer вызывалась функция OnTimer совершенно другого класса.
Of course, the code must be complete enough to compile and link.
Re[6]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 12:01
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Что такое вот это

L_L>m_Timer.OnTimer = (TNotifyEvent) OnTimer;?

Потому что...
typedef void (CObject::* TNotifyEvent)(CObject* Sender);


если так (m_Timer.OnTimer = OnTimer то

cannot convert parameter 1 from 'void (__thiscall Timer::CWaitChoice::* )(ufo::CObject *)' to 'ufo::TNotifyEvent'
-= The Alien//Ufocomp =-
Re[7]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 12:03
Оценка:
Не стоит считать меня таким уж деревом. Лучше подумай еще раз над моим вопросом.
Of course, the code must be complete enough to compile and link.
Re[6]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 12:45
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Вникать во все это неохота. Но, сдается мне, что ты хочешь чтоб для объекта m_timer вызывалась функция OnTimer совершенно другого класса.


Да нет, CWaitChoice нужет только потому что CTimer является частью библиотеки ufoLib где у всех классов потомком является CObject. По этой причине написать просто так:
    void OnTimer(CObject *Sender)
    {
        
    };

    bool WaitChoice(const DWORD dwSec)
    {
        CTimer Timer;
        Timer.OnTimer = (TNotifyEvent) OnTimer;

...нельзя Choice error C2440: 'type cast' : cannot convert from 'void (__cdecl *)(ufo::CObject *)' to 'ufo::TNotifyEvent' нужен класс контейнер от CObject.

просто вся фигня в том что внутри OnTimer члены класса берутся не понятно от куда и их лубые изминенеия не как не отражаются на самом классе. Если смотреть по дебагеру то пулячается следуещие:
Адрес this класса CWaitChoice 0x0012fdd4
Адрес this класса CTimer 0x0012fde0
Гогда вызываем void CWaitChoice::OnTimer, this должен быть 0x0012fdd4, а он 0x0012fde0.
Я грешу на:
    void CTimer::Timer(void)
    {
        if ( m_OnTimer != NULL )
            (this->*m_OnTimer)(this);
    };


и на что мне это заменить так чтобы все работало правильно я не знаю... Вот...
-= The Alien//Ufocomp =-
Re[6]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 12:52
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Вникать во все это неохота. Но, сдается мне, что ты хочешь чтоб для объекта m_timer вызывалась функция OnTimer совершенно другого класса.


Сорри... чего-то я торможу...

Да все верно именно это мне и нужно....
-= The Alien//Ufocomp =-
Re[7]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 12:58
Оценка:
Еще раз.
Есть
CObject CObject
| |
CTimer CWaitChoice

У CWaitChoice есть функция OnTimer(), которая обращается к членам этого класса
Ты, преобразовывая указатель на член-функцию (кстати, адрес ее берется так &CWaitChoice::OnTimer), хочешь писать (m_Timer.*OnTimer)() ???? Но ведь у твоего CTimer нет тех членов, с которыми работает CWaitChoice::OnTimer ?
Of course, the code must be complete enough to compile and link.
Re[8]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 13:12
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Еще раз.

L_L>Есть
L_L>CObject CObject
L_L> | |
L_L>CTimer CWaitChoice

L_L>У CWaitChoice есть функция OnTimer(), которая обращается к членам этого класса

L_L>Ты, преобразовывая указатель на член-функцию (кстати, адрес ее берется так &CWaitChoice::OnTimer), хочешь писать (m_Timer.*OnTimer)() ???? Но ведь у твоего CTimer нет тех членов, с которыми работает CWaitChoice::OnTimer ?

Есть CTimer от CObject
есть CWaitChoice от CObject

В CWaitChoice объявлен CTimer m_Timer

class CWaitChoice: public CObject
    {
    private:

        DWORD        m_CallCount;
        bool        m_Terminate;
        CTimer        m_Timer;

    protected:

        void OnTimer(CObject* Sender);
        void Terminate(void);

    public:

        CWaitChoice(): m_CallCount(0), m_Terminate(false)
        {
            m_Timer.Interval = 250;
            m_Timer.OnTimer = (TNotifyEvent) OnTimer;
        };
...

есть:
void CWaitChoice::OnTimer(CObject* Sender)
{
    m_CallCount++;

    if ( kbhit() )
        Terminate();
};

вызывается CWaitChoice::OnTimer из CTimer:
void CTimer::Timer(void)
{
    if ( m_OnTimer != NULL )
        (this->*m_OnTimer)(this);
};


И когда вызывается CWaitChoice::OnTimer(CObject* Sender) то m_CallCount не равна 0 как должно выть она вообще не от мира сего... и соответственно чтобы я не делал с членами класса CWaitChoice внутри CWaitChoice::OnTimer на сам класс CWaitChoice это не как не отражается. Вот такая вот херня...
-= The Alien//Ufocomp =-
Re[9]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 13:12
Оценка:
Здравствуйте, alienufo, Вы писали:
И я тебе уже сказал почему это так.
Of course, the code must be complete enough to compile and link.
Re[10]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 13:26
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, alienufo, Вы писали:

L_L>И я тебе уже сказал почему это так.

Ну хорошо как мне не преобразовывать указатель на член-функцию или другими словами как мне вызвать функцию одного класса из другого?

По тому, что по другому не компелируется!
-= The Alien//Ufocomp =-
Re[9]: Как вызвать переменную объявленную как функция?
От: Михаил Трухманов Россия  
Дата: 16.06.03 13:29
Оценка:
Здравствуйте, alienufo, Вы писали:

A>
A>void CTimer::Timer(void)
A>{
A>    if ( m_OnTimer != NULL )
A>        (this->*m_OnTimer)(this);
A>};
A>


A>И когда вызывается CWaitChoice::OnTimer(CObject* Sender) то m_CallCount не равна 0 как должно выть она вообще не от мира сего... и соответственно чтобы я не делал с членами класса CWaitChoice внутри CWaitChoice::OnTimer на сам класс CWaitChoice это не как не отражается. Вот такая вот херня...


Вызывать m_OnTimer можно только у объектов типа CWaitChoice (после присвоения m_Timer.OnTimer = (TNotifyEvent) OnTimer

А ты пишешь (this->*m_OnTimer)(this); где this -- типа CTimer.
Вороятно тебе нужно
либо еще рядом с m_OnTimer запоминать адрес объекта, у которого надо вызвать эту функцию (если они в принципе возможны разных типов),
либо завести предка (интерфейс) с виртуальной функцией OnTimer, и хранить не m_OnTimer, а указатель на объект, котрый реализует этот интерфейс (функциею OnTimer)
Re[11]: Как вызвать переменную объявленную как функция?
От: Lorenzo_LAMAS  
Дата: 16.06.03 13:35
Оценка:
Все дело в неправильном дизайне?
Эх, попробую так объяснить.
class Base{};
class Der1:public Base{};
class Der2:public Base
{
public:
   Der2():i_(0)
   {
   }
   void fun()
   {
      ++i_;
   }
   void fun1()
   {
        (d_.*static_cast<void (Base::*)()>(&::Der2::fun))();//***
   }
private:
   int i_;
   Der1 d_;
};


Это то, что ты хотел, не так ли?

Ну так вот, класс Base и Derived — пустые (размер их, допустим, 1 байт).

Ты преобразовал указатели т.д. и т.п и вызываешь функцию.
Твоя функция в *** получает указатель this, который указывает вовсе не на объект Der2, но ты пытаешься менять значение несуществующего целого числа. Не так ли?
Of course, the code must be complete enough to compile and link.
Re[12]: Как вызвать переменную объявленную как функция?
От: alienufo Россия  
Дата: 16.06.03 14:45
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Все дело в неправильном дизайне?


Не думаю, дизайнеры Borland!

L_L>Это то, что ты хотел, не так ли?

В целом да но реализация иная...

L_L>Твоя функция в *** получает указатель this, который указывает вовсе не на объект Der2, но ты пытаешься менять значение несуществующего целого числа. Не так ли?


Дело не в this я его просто передаю, далее не работаю с ним!!!

Еще раз и наверное последний, а то я совсем не въезжаю...

Что мне надо?

есть

class Base{};

typedef void (Base::* NE)(Base* S);

class Der1:public Base
{
protected:

  virtual TT(void)
  {
    (this->*T)(this);
  };

public:
  NE T;    

};

class Der2:public Base
{
private:
   int i;
   Der1 d;

public:

   Der2():i(0)
   {
     d.T = (NE) fun;
   }

   void fun()
   {
      ++i;
   }

   int GetI(void)
   {
     return i; 
   }
};

// Далее

Der2 der2;

// TT вызывается через API как не важно... предположим вызвал 10 раз что будет здесь?:

cout << der2.GetI << endl;

// я могу сразу сказать что будет: 0
-= The Alien//Ufocomp =-
Re[13]: Как вызвать переменную объявленную как функция?
От: WolfHound  
Дата: 16.06.03 17:14
Оценка:
Здравствуйте, alienufo, Вы писали:

A>Не думаю, дизайнеры Borland!

BCB Это самый поганый компилятор из тех что я видел. Буквально сегодня пол дня ловил AV на пустом месте... оказалось что конструктор по умолчанию basic_string вошол в бесконечную рекурсию и выжрал весь стек но в место переполнения стека вылетело AV по 0.... Благо замена на AnsiString подходила без особого гемороя.
Да и VCL на дельфих написана.... а С++ не дельфя и что нормально для дельфи очень криво для С++.

A>Еще раз и наверное последний, а то я совсем не въезжаю...

Так работать не будет по определению.
Завтра доберусь до билдера посмотрю что тебе может помочь.

A>// я могу сразу сказать что будет: 0

А я могу сказать что гдето память испортилась, а AV по случайности не вылетел.
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.