Russian Qt Forum
Ноябрь 24, 2024, 18:01 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Указатели на методы производных классов  (Прочитано 4887 раз)
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« : Октябрь 07, 2014, 23:30 »

Коллеги,
нужно с помощью функции базового класса вызывать невиртуальные функции производного класса. Виртуальные использовать не хотелось бы, т.к. в разных производных классах используются разные функции, хотя и с одинаковой сигнатурой. Поэтому загромождать базовый класс не хотелось бы. Хотя этот вариант тоже остается.
Один из вариантов такой:
Код:
class Unit
{
protected:
    typedef void (Unit::* PtrFun)();
    typedef QMap<int,PtrFun> Operations;
    Operations operations;

public:
    virtual ~Unit() {}

    void run(int n){
        PtrFun fun=operations.value(n,0);
        if(fun)
            (this->*fun)();
    }
};

class Relay : public Unit
{
public:
    Relay(){
        operations[1] = PtrFun(&Relay::on);
        operations[2] = PtrFun(&Relay::off);
    }

    void on();
    void off();
};
Используется это так:
Код:
    unit = new Relay();
    unit->run(1);
    unit->run(2);
Компилятор приходится нагибать явным приведением типа (PtrFun(&Relay::on)), но, вроде бы, это не должно выстрелить - указатель &Relay::on является смещением в адресном пространстве объекта Relay, и приведение типа не должно изменить его значение. А вызов функции связан с объектом этого типа (this указывает на объект Relay).
Коллеги, на ваш взгляд, можно ли без опаски использовать такое?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Октябрь 08, 2014, 01:59 »

А почему не использовать std::function + std::bind?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Октябрь 08, 2014, 09:10 »

указатель &Relay::on является смещением в адресном пространстве объекта Relay,
Если метод on не виртуальный то по-моему просто адрес ф-ции. Так часто делают в С где нет virtual, разница в досылке this
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #3 : Октябрь 08, 2014, 09:56 »

А почему не использовать std::function + std::bind?
Спасибо, слишком сложно и мутно.. Уж проще в базовом классе объявить виртуальные пустышки, а в наследнике тогда написать честные
Код:
        operations[1] = &Unit::on;
        operations[2] = &Unit::off;
А по сути вопроса?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #4 : Октябрь 08, 2014, 09:59 »

Если метод on не виртуальный то по-моему просто адрес ф-ции.
Увы, это не так. Адрес функции-члена связан всегда с объектом. Иначе как бы эта функция работала с членами-данными класса?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #5 : Октябрь 08, 2014, 10:26 »

Сложно и муторно?
/* Писал прямо здесь - могут быть опечатки. */
Код
C++ (Qt)
class Unit
{
protected:
   typedef QMap<int,std::function> Operations;
   Operations operations;
 
public:
   virtual ~Unit() {}
 
   void run(int n)
   {
       operations[ n ]();
   }
};
 
class Relay : public Unit
{
public:
   Relay(){
       operations[1] = std::bind( &Relay::on, this );
       operations[2] = std::bind( &Relay::off, this );
   }
 
   void on();
   void off();
};
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Октябрь 08, 2014, 11:40 »

Увы, это не так. Адрес функции-члена связан всегда с объектом. Иначе как бы эта функция работала с членами-данными класса?
По-моему никак не связан. Хранится адрес + дельта. Адреc для не виртуала - просто адрес, для виртуала - смещение в VMT. Дельта роялит только для множественного наследования, иначе нулевая (хоть виртуал хоть нет).

Примечание: следующее предложение - просто что я видел в отладчике (т.е. не факт)
При вызове если адрес (первое поле) четный - невиртуал, нечетный - виртуал, и там разбирается.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #7 : Октябрь 08, 2014, 12:05 »

Сложно и муторно?
/* Писал прямо здесь - могут быть опечатки. */
std::function это шаблон, не так ли? Поэтому не хватает еще одного typedef.
Но у меня все рабно не получилось. Это, случаем, не C++11? Простого инклуда <functional> не хватает.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Октябрь 08, 2014, 12:08 »

Это, случаем, не C++11? Простого инклуда <functional> не хватает.
Да, если у вас более ранний стандарт, то тоже есть в boost - хедеронли.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #9 : Октябрь 08, 2014, 12:12 »

По-моему никак не связан.
Вызов функции-члена по указателю может быть произведен только с использованием указателя на объект p->*fun() либо самого объекта obj.*fun() и никак иначе.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Октябрь 08, 2014, 12:30 »

Вызов функции-члена по указателю может быть произведен только с использованием указателя на объект p->*fun() либо самого объекта obj.*fun() и никак иначе.
Само собой, но никаких данных экземпляра указатель на ф-цию не хранит. Он умеет находить адрес в VMT - и то в случае виртуала. Поэтому не вижу какая опасность Вам угрожает  Улыбающийся
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #11 : Октябрь 08, 2014, 13:33 »

Ну и славно.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.288 секунд. Запросов: 23.