Конечный автомат и паттерн Command...
От: Faust Россия  
Дата: 21.09.04 11:44
Оценка:
Возможна ли подобная конструкция, и если возможна, то где ошибка в моей реализации?

template <typename TExecuter>
class TCommand
{
public:
    typedef int (TExecuter::*Action)(void*);

    TCommand(TExecuter* pExecuter, Action pfnAction)
        : m_pExecuter(pExecuter)
        , m_pfnAction(pfnAction) { }

private:
    TExecuter*                m_pExecuter;
    Action                    m_pfnAction;

public:
    virtual int                Execute(void* pvParam)
    { return (m_pExecuter->*m_pfnAction)(pvParam); }
};

class CCommand
{
public:
    virtual int                Execute(void* pvParam) { return 0; }
};

class CReceiveFile : public CCommand
{
public:
    int                        Execute(void* pvParam)
    {
        char*    szParam = static_cast<char*> (pvParam);
        int        iLen = strlen(szParam);
        for(int i=0, j=iLen-1; i<iLen/2; i++, j--)
        {
            szParam[i] = szParam[i] ^ szParam[j];
            szParam[j] = szParam[j] ^ szParam[i];
            szParam[i] = szParam[i] ^ szParam[j];
        }
        return iLen;
    }

private:
    // На что повлияет введение этой переменной?
    HANDLE                    m_hFile;
};

class CProtocol
{
public:
    enum ECommads
    {
        Command = 1, 
        Server, 
        Client, 
        Request, 
        Answer, 
        File
    };

private:
    ECommads                m_eCommands;
    TCommand<CCommand>*        m_pCommand;

public:
    CProtocol() : m_eCommands(File), m_pCommand(NULL) { }
    ~CProtocol() {}

    int                        Process(void* pvBuffer)
    {
        switch(m_eCommands)
        {
        Server:
            break;
        Client:
            break;
        Request:
            break;
        Answer:
            break;
        File:
            // здесь траблы с типами, что я делаю не так?
            m_pCommand = reinterpret_cast<TCommand<CCommand>*>
                ((new CReceiveFile()), (&CReceiveFile::Execute));
            break;
        }
        // Безопасен ли этот вызов?
        return m_pCommand->Execute(pvBuffer);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    char        szTest[] = "abcdefg";
    CProtocol*    pProtocol = new CProtocol();
    pProtocol->Process(szTest);
}
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re: Конечный автомат и паттерн Command...
От: Кодт Россия  
Дата: 21.09.04 11:52
Оценка:
Здравствуйте, Faust, Вы писали:

F>Возможна ли подобная конструкция, и если возможна, то где ошибка в моей реализации?


F>
F>m_pCommand = reinterpret_cast<TCommand<CCommand>*>((new CReceiveFile()), (&CReceiveFile::Execute));

Это ты нагородил. В скобках у тебя оператор запятая, а вовсе не конструктор команды.
Нужно так:
m_pCommand = new TCommand<CCommand>( new CReceiveFile(), &CReceiveFile::Execute );


[c]
F>// Безопасен ли этот вызов?
F>return m_pCommand->Execute(pvBuffer);
F>[/ccode]
Да, если m_pCommand — валидный указатель на валидный объект

Кстати. А кто будет мусор убирать?
Перекуём баги на фичи!
Re[2]: Конечный автомат и паттерн Command...
От: Faust Россия  
Дата: 21.09.04 12:10
Оценка:
Здравствуйте, Кодт, Вы писали:

F>>
F>>m_pCommand = reinterpret_cast<TCommand<CCommand>*>((new CReceiveFile()), (&CReceiveFile::Execute));
К>

К>Это ты нагородил. В скобках у тебя оператор запятая, а вовсе не конструктор команды.
К>Нужно так:
К>
К>m_pCommand = new TCommand<CCommand>( new CReceiveFile(), &CReceiveFile::Execute );
К>

Неа, не катит. Кричит следующее:
error C2664: 'TCommand<TExecuter>::TCommand(TExecuter *,TCommand<TExecuter>::Action)' : cannot convert parameter 2 from 'int (__thiscall CReceiveFile::* )(void *)' to 'TCommand<TExecuter>::Action'
        with
        [
            TExecuter=CCommand
        ]
        and
        [
            TExecuter=CCommand
        ]
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
d:\Faust\Projects\Win\MainCL\Main.cpp(211) : warning C4060: switch statement contains no 'case' or 'default' labels


К>Кстати. А кто будет мусор убирать?

Для простоты опустил, нужно быстренько наваять демо-версию, ньюансы потом... Вся эта рутина будет делаться внутри протокола.
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re[3]: Конечный автомат и паттерн Command...
От: Кодт Россия  
Дата: 21.09.04 12:29
Оценка: 3 (1) +1
Здравствуйте, Faust, Вы писали:

F>Неа, не катит.

m_pCommand = new TCommand<CCommand>(
               new CReceiveFile(),
               static_cast< TCommand<CCommand>::Action> >(&CReceiveFile::Execute)
             );

Вот так должно прокатить.
Перекуём баги на фичи!
Re[4]: Конечный автомат и паттерн Command...
От: Вадим Никулин Россия Здесь
Дата: 21.09.04 12:38
Оценка: 3 (1) +1
Здравствуйте, Кодт, Вы писали:

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


F>>Неа, не катит.

К>
К>m_pCommand = new TCommand<CCommand>(
К>               new CReceiveFile(),
К>               static_cast< TCommand<CCommand>::Action> >(&CReceiveFile::Execute)
К>             );
К>

К>Вот так должно прокатить.

А зачем? Можно просто &CCommand::Execute — она ведь виртуальная.
Re[4]: Конечный автомат и паттерн Command...
От: Faust Россия  
Дата: 21.09.04 12:44
Оценка:
Здравствуйте, Кодт, Вы писали:

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


F>>Неа, не катит.

К>
К>m_pCommand = new TCommand<CCommand>(
К>               new CReceiveFile(),
К>               static_cast< TCommand<CCommand>::Action> >(&CReceiveFile::Execute)
К>             );
К>

К>Вот так должно прокатить.

я пробовал так:
reinterpret_cast< TCommand<CCommand>::Action >(&CReceiveFile::Execute)
и так:
reinterpret_cast< TCommand<CCommand>::*Action >(&CReceiveFile::Execute)
Скажи, в чем отличие этих двух вариантов между собой и твоим вариантом?
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re[5]: Конечный автомат и паттерн Command...
От: Кодт Россия  
Дата: 21.09.04 12:58
Оценка:
Здравствуйте, Faust, Вы писали:

Скажи, в чем отличие этих двух вариантов между собой и твоим вариантом?

В том, что static_cast грамотно приводит указатели на члены, а реинтерпрет — грубо говоря, побитово копирует.

Где бы гвоздями прибить на видном месте: не пользуйтесь реинтерпретом, если не знаете, что он сделает!
Перекуём баги на фичи!
Re[6]: Конечный автомат и паттерн Command...
От: Faust Россия  
Дата: 21.09.04 13:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>В том, что static_cast грамотно приводит указатели на члены, а реинтерпрет — грубо говоря, побитово копирует.


К>Где бы гвоздями прибить на видном месте: не пользуйтесь реинтерпретом, если не знаете, что он сделает!


Добро, давай тогда прибьем этот гвоздь!!!
Объясни разницу между этими двумя приведениями типов на примере этих двух классов:
class Base
{
public:
    bool                    m_bFlag;

    Base() : m_bFlag(false)

    virtual bool            Process0(void) = 0;
    virtual bool            Process1(void) { return m_bFlag; }
}

class DerivedLevel1 : public Base
{
public:
    int                        m_iParam;

    DerivedLevel1() : m_iParam(0)

    virtual bool            Process0(void) { m_bFlag = true; m_iParam++; }
    virtual bool            Process1(void) { return m_bFlag; }
}

int _tmain(int argc, _TCHAR* argv[])
{
    Base*        pBaseFirst = static_cast<Base*> (new DerivedLevel1());
    Base*        pBaseSecond = reinterpret_cast<Base*> (new DerivedLevel1());
}
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re[7]: Конечный автомат и паттерн Command...
От: Кодт Россия  
Дата: 21.09.04 13:33
Оценка:
Здравствуйте, Faust, Вы писали:

К>>Где бы гвоздями прибить на видном месте: не пользуйтесь реинтерпретом, если не знаете, что он сделает!


F>Добро, давай тогда прибьем этот гвоздь!!!

F>Объясни разницу между этими двумя приведениями типов на примере этих двух классов:

Давай немного перепишем их.
class Base1
{
  char x[100];
};

class Base2
{
public:
  virtual void foo() {}
};

class Derived: public Base1, public Base2
{
public:
  virtual void foo() {}
};

main()
{
  Derived* p0 = new Derived();
  Base2* p1 = static_cast<Base2*>(p0);
  Base2* p2 = reinterpret_cast<Base2*>(p0);
}

Всё ещё не видишь разницу?
Перекуём баги на фичи!
Re: Конечный автомат и паттерн Command...
От: _Winnie Россия C++.freerun
Дата: 21.09.04 21:38
Оценка:
Возможно, я оффтопю, может тебе понравятся Closure
Автор: _Winnie
Дата: 19.09.04
или boost::function?
Правильно работающая программа — просто частный случай Undefined Behavior
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.