Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Шаблон класса 
:(
    Опции темы
zss
Дата 17.12.2005, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Есть немного странная задача.

Нужно создать класс (на основе шаблонов) который мог бы вызывать функции 2 типов.

1 тип - обычная функция
2 тип - метод класса

например
Код

class Caller {
    private:
        typedef unsigned (__stdcall *PFUNC_THREAD)(void *);

        PFUNC_THREAD func_;
        Caller (const Caller& copy);
        Caller& operator = (const Caller& copy);

    public:
        Caller(PFUNC_THREAD func, void *arg)  : func_(func);
        virtual ~Caller () {}
        virtual void Call(void) const {
            (func_)(arg_);
        }
};


и
Код

template <class T>
class Caller {
    private:
        typedef unsigned (T::*Func)(void *arg);
        T *obj_;
        Func func_;
        void *arg_;

        Caller (const Caller& copy);
        Caller& operator = (const Caller& copy);

    public:
        Caller(T *obj, Func func, void *arg) :
               obj_(obj), func_(func), arg_ (arg){}

        virtual ~Caller () {}
        virtual void Call(void) const {
            (obj_->*func_)(arg_);
        }
};


только вот зотелось бы с помощью шаблонов создать один класс, который в конструкторе будет принимать указатель либо на фуннкцию, либо на метод - ну и соответственно дергать нужную
PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Метод в лоб, пишу на коленке, выдумывать элегантное решение в лом

Код


struct Caller_Impl
{
  virtual void call()=0;
};


template  <class _Tp>
struct Caller_Method : public  Caller_Impl
{
      Caller_Method (_Tp* ptr, void(_Tp::*f)(void*), void* arg) : m_ptr(ptr), m_arg(arg), m_func(f){}
      void call(){
        (m_ptr->*m_func)(m_arg);
      }    
     _Tp* m_ptr;
     void* m_arg;
     void (_Tp::*m_func) (void*);
};

struct Caller_Function : public  Caller_Impl
{
      Caller_Function(void (*f)(), void* arg) :  m_func(f), m_arg(arg){}
      void call(){
        m_func(m_arg);
      }    
     void* m_arg;
     void (*m_func) (void*);
};

struct Caller
{
     template<class _T>
     Caller(T* cl, void(T::*func)(), void* arg ){
          m_caller = new Caller_Method<T>(cl,func,arg);
     }

     Caller(void (*func)(), void* arg){
          m_caller = new Caller_Function(func,arg);
     }
    void call(){
       m_caller->call();
    }
    CallerImpl* m_caller;
};

Думаю идея понятна smile

Это сообщение отредактировал(а) Mayk - 17.12.2005, 19:52


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 17.12.2005, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Mayk, спасибо - хорошее решение


Цитата(Mayk @ 17.12.2005, 19:50)
выдумывать элегантное решение в лом


а что - можешь еще лучше предложить smile

PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Могу предложить попробовать обойтись без использования доп классов. Правда это нечитабельнее

Что-то типа (часть кода за вызов ф-ции и очевидный деструктор опущу)
Код

class Caller
{
 template<class _Tp>
 Caller(_Tp* ptr, void (_Tp::*fn)(), void* arg ){    
        typedef void (_Tp::*Method)(void*);

    call_impl = &Caller::callMethod<_Tp> ; 
    m_data = new char[sizeof(_Tp*) +  sizeof(Method) +  sizeof(void*)];  //m_data = { _Tp*, func(), arg}
    char* p = m_data;
    memcpy(p, ptr, sizeof(ptr));  p+= sizeof(ptr);
    memcpy(p, fn, sizeof(fn));  p+= sizeof(fn);
    memcpy(p, arg, sizeof(arg)); 
 }

 void call(){
   call_impl();
 }

 template<class _Tp>
 void callMethod(){
       char* p = m_data;
       _Tp* ptr;  
       Method* fn;
       void* arg;
        typedef void (_Tp::*Method)(void*);

    memcpy(ptr,p, sizeof(ptr));  p+= sizeof(ptr);
    memcpy(fn,p, sizeof(fn));  p+= sizeof(fn);
    memcpy(arg,p, sizeof(arg)); 
     
          (ptr->*m)(p);
 }

 void (Caller::*call_impl)(void*);
 сhar* m_data;
};

Не сказал бы что это лучше :-)
Вывод - очевидные решения предпочтительнее неочевидных smile

Это сообщение отредактировал(а) Mayk - 17.12.2005, 20:28


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 17.12.2005, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Mayk, что-то никак не соберу

Код

class CallerImpl {

    private :
        CallerImpl (const CallerImpl& copy);
        CallerImpl& operator = (const CallerImpl& copy);

    protected :
        void *arg_;
        CallerImpl () : arg_ (NULL) {}
        virtual ~CallerImpl () {}

    public :
        virtual void Call(void) const = 0;
};
/*----------------------------------------------------------------------------*/
class StaticCaller : private CallerImpl {

    private :
        typedef unsigned (__stdcall *Func)(void *);
        const Func func_;

        StaticCaller (const StaticCaller& copy);
        StaticCaller& operator = (const StaticCaller& copy);

        virtual void Call (void) const { func_ (arg_); }

    public :
        StaticCaller (Func func, void *arg) : func_(func), arg_ (arg) {}
        virtual ~StaticCaller () {}

};
/*----------------------------------------------------------------------------*/
template <class T>
class ClassCaller : private CallerImpl {

    private :
        typedef unsigned (T::*Func)(void *arg);
        const T *obj_;
        const Func func_;

        ClassCaller (const ClassCaller& copy);
        ClassCaller& operator = (const ClassCaller& copy);

        virtual void Call (void) const { (obj_->*func_) (arg); }

    public :
        ClassCaller (T *obj, Func func, void *arg) :
                     obj_(obj), func_(func) { arg_ = arg; }
        virtual ~ClassCaller () {}


};

/*----------------------------------------------------------------------------*/
class MyClass {
    private :
        CallerImpl caller_;

    public :
        template <class T>
        MyClass (T *obj, unsigned (T::*Func)(void *), void *arg) : caller_(NULL) {
            caller_ = new ClassCaller (obj, Func, arg);
        }

        MyClass (unsigned (__stdcall *Func)(void *), void *arg) : caller_(NULL) {
            caller_ = new StaticCaller (Func, arg);
        }
};


не хочет так smile

Это сообщение отредактировал(а) zss - 17.12.2005, 21:15
PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Почитай сообщения об ошибках smile

Код

class CallerImpl {
    private :
        CallerImpl (const CallerImpl& copy);
        CallerImpl& operator = (const CallerImpl& copy);
    protected :
        void *arg_;
        CallerImpl () : arg_ (NULL) {}
        virtual ~CallerImpl () {}
    public :
        virtual void Call(void) const = 0;
};
/*----------------------------------------------------------------------------*/
class StaticCaller : public CallerImpl {
    private :
        typedef unsigned (*Func)(void *);
        const Func func_;
        StaticCaller (const StaticCaller& copy);
        StaticCaller& operator = (const StaticCaller& copy);
        virtual void Call (void) const { func_ (arg_); }
    void* arg_;
    public :
        StaticCaller (Func func, void *arg) : func_(func), arg_ (arg) {}
        virtual ~StaticCaller () {}
};
/*----------------------------------------------------------------------------*/
template <class T>
class ClassCaller : public CallerImpl {
    private :
        typedef unsigned (T::*Func)(void *arg);
        const T *obj_;
        const Func func_;
        ClassCaller (const ClassCaller& copy);
        ClassCaller& operator = (const ClassCaller& copy);
        virtual void Call (void) const { (obj_->*func_) (arg); }
    public :
        ClassCaller (T *obj, Func func, void *arg) :
                     obj_(obj), func_(func) { arg_ = arg; }
        virtual ~ClassCaller () {}
};
/*----------------------------------------------------------------------------*/
class MyClass {
    private :
        CallerImpl* caller_;
    public :
        template <class T>
        MyClass (T *obj, unsigned (T::*Func)(void *), void *arg) : caller_(NULL) {
            caller_ = new ClassCaller<T> (obj, Func, arg);
        }
        MyClass (unsigned (*Func)(void *), void *arg) : caller_(NULL) {
            caller_ = new StaticCaller (Func, arg);
        }
};



--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 17.12.2005, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Mayk, я так понимаю ты подправил

Код

ClassCaller[b]<T>[/b]


мой косяк - упустил smile

Код

class StaticCaller : public CallerImpl {
    private :
        void* arg_;  // Зачем еще раз ?




говорит, что не может конвертнуть StaticCaller* в Callerimpl* - странно ...
PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(zss @ 18.12.2005, 02:11)
void* arg_;  // Зачем еще раз ?

g++ ругался, что arg_ не найден.
Добавлено @ 22:15
Стоп. Понял.

Цитата(zss @ 18.12.2005, 01:12)
        StaticCaller (Func func, void *arg) : func_(func), arg_ (arg) {}

Так нельзя - arg_ принадлежит базовому классу, который УЖЕ проинициализирован. => инициализировать его нельзя



--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 17.12.2005, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Цитата(Mayk @ 17.12.2005, 22:13)
Так нельзя - arg_ принадлежит базовому классу, который УЖЕ проинициализирован. => инициализировать его нельзя


значит придется заводить arg_ для каждого наследника ?

З.Ы. Попробовал - не прокатило

Это сообщение отредактировал(а) zss - 17.12.2005, 22:21
PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(zss @ 18.12.2005, 02:18)

значит придется заводить arg_ для каждого наследника ?

Не обязательно
Цитата(zss @ 18.12.2005, 01:12)
        ClassCaller (T *obj, Func func, void *arg) :
                    obj_(obj), func_(func) { arg_ = arg; }

Вот это работает smile
Добавлено @ 22:24
Цитата(zss @ 18.12.2005, 02:18)

З.Ы. Попробовал - не прокатило


Цитата(zss @ 18.12.2005, 01:12)
virtual void Call (void) const { (obj_->*func_) (arg); }

компилятор даже знает почему


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 17.12.2005, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



это ошибки из-за большого количества спиртного smile

Код

class CallerImpl {

    private :
        CallerImpl (const CallerImpl& copy);
        CallerImpl& operator = (const CallerImpl& copy);

    protected :
        void *arg_;
        CallerImpl () : arg_ (NULL) {}
        virtual ~CallerImpl () {}
        virtual void Call(void) const = 0;

};
/*----------------------------------------------------------------------------*/
class StaticCaller : private CallerImpl {

    private :
        typedef unsigned (*Func)(void *);
        Func func_;

        StaticCaller (const StaticCaller& copy);
        StaticCaller& operator = (const StaticCaller& copy);

        virtual void Call (void) const { func_ (arg_); }

    public :
        StaticCaller (Func func, void *arg) : func_(func), arg_ (arg) {}
        virtual ~StaticCaller () {}

};
/*----------------------------------------------------------------------------*/
template <class T>
class ClassCaller : private CallerImpl {

    private :
        typedef unsigned (T::*Func)(void *arg);
        T *obj_;
        Func func_;

        ClassCaller (const ClassCaller& copy);
        ClassCaller& operator = (const ClassCaller& copy);

        virtual void Call (void) const { (obj_->*func_) (arg_); }

    public :
        ClassCaller (T *obj, Func func, void *arg) :
                     obj_(obj), func_(func), arg_ (arg) {}
        virtual ~ClassCaller () {}


};

/*----------------------------------------------------------------------------*/


говорит
Код

'constructor' is not an unambiguous base class of 'class'    

PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(zss @ 18.12.2005, 02:33)
        ClassCaller (T *obj, Func func, void *arg) :
                    obj_(obj), func_(func), arg_ (arg) {}

Ну и зачем? arg_ нельзя инициализировать. Он уже инициализирован в базовом классе. => надо писать
arg_=arg, как и было раньше.

Цитата(zss @ 18.12.2005, 02:33)
'constructor' is not an unambiguous base class of 'class'   

где говорит?


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 17.12.2005, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Цитата(Mayk @ 17.12.2005, 22:42)
где говорит?



Код

class MyClass {
    private :
        CallerImpl* caller_;

    public :
        template <class T>
        MyClass (T *obj, unsigned (T::*Func)(void *), void *arg) : caller_(NULL) {
            caller_ = new ClassCaller<T> (obj, Func, arg);
        }
        MyClass (unsigned (*Func)(void *), void *arg) : caller_(NULL) {
            caller_ = new StaticCaller (Func, arg); // здесь
        }
};



PM MAIL ICQ   Вверх
Mayk
Дата 17.12.2005, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Замени private наследование на public


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
zss
Дата 18.12.2005, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: 1
Всего: 2



Mayk, спасибо - вроде собралось smile

Еще вопрос - эти 2 конструктора придется всегда за собой таскать и для порожденных классов ? Если да - то можно ли что-нибудь придумать (чтоб не таскать - хотя есть большие подозрения, что нельзя smile)
PM MAIL ICQ   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1010 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.