Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.88/32: Рейтинг темы: голосов - 32, средняя оценка - 4.88
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30

Использование указателя на метод вместо виртуального метода

20.11.2010, 12:33. Показов 7225. Ответов 45
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется базовый класс Base. Имеется производный от Base класс Derived. В классе Derived требуется выполнить некоторое действие, которое практически полностью эквивалентно для любого производного от Base класса, за исключением небольшого фрагмента.

Схематично код выглядит так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Base
{
  void Exec (void)
  {
    // общие действия
    ...
 
    // конкретные действия для производных классов
    Tail ();
  }
 
  virtual void Tail (void) = 0;
};
 
class Derived : public Base
{
  void MyExec (void)
  {
    // В процессе исполнения будет исполнен виртуальный метод Tail
    Exec ();
  }
 
  virtual void Tail (void)
  {
    // Определяем конкретные действия для нашего класса
  }
}
Однако при такой схеме возможен только один вид частных действия для производного класса. А хотелось бы, чтобы внутри производного класса можно было выполнять разные действия. Для этого логично было бы использовать указатель на метод. Т.е. что-то типа такого

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Base
{
  void Exec (void (Base::*tail)(void))
  {
    // общие действия
    ...
 
    // конкретные действия для производных классов
    // здесь уже через указатель  на метод
    (this->*tail) ();
  }
};
 
class Derived : public Base
{
  void MyExec (void)
  {
    // Выполняем основные действия с двумя разными типами
    // частных действий. Необходимую операцию преобразования
    // указателя на метод опускаю, чтобы глаза не резало
    Exec (Tail1);
    Exec (Tail2);
  }
 
  void Tail1 (void)
  {
    // Определяем конкретные действия "вариант1" для нашего класса
  }
 
  void Tail2 (void)
  {
    // Определяем конкретные действия "вариант2" для нашего класса
  }
}
Собственно вопрос: насколько опасным является преобразование указателя на метод в данном случае. Опасность не столько в преобразовании указателя на метод, сколько в том, что при вызове Derived-метода через указатель на класс Base может прийти кривой this. Понятно, что в случае "простого" наследования ничего страшного нет. Будет ли что-то криво работать в случае множественных или виртуальных наследований или в каких-то ещё тяжёлых случаев. Или такой способ при некоторых ограничениях на тип наследования можно считать надёжным и корректным? Можно ли как-то сделать статический контроль в случаях, когда такой вариант оказывается некорректным?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.11.2010, 12:33
Ответы с готовыми решениями:

Вызов виртуального метода базового класса из указателя производного
Допустим есть такой код: #include <iostream> class Base { public: virtual void f() { std::cout << "Base\n"; } ...

Почему при переопределении виртуального метода в производном классе выводится метод базового?
Всем добра! Помогите разобраться почему при переопределении виртуального метода в производном классе выводится метод базового ? По идеи...

Использовать метод transform() вместо метода sort()
Добрый день , надо исправить код , заменив метод sort() , методом transform(), не могу уловить функцию и способ использование transform()....

45
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
17.04.2011, 11:49
Студворк — интернет-сервис помощи студентам
Ну да. Но зато переносимо. Можно использовать хоть стопятьсот методов, использовать разное количество и типы параметров...
В общем, везде свои недостатки.)

Добавлено через 47 секунд
Цитата Сообщение от Evg Посмотреть сообщение
Чтобы обеспечить раздельный запуск методов, тебе придётся описывать два пользовательских класса Functor.
Нет. Нужно два виртуальных метода в функторе.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
17.04.2011, 12:00  [ТС]
Цитата Сообщение от Deviaphan Посмотреть сообщение
Ну да. Но зато переносимо. Можно использовать хоть стопятьсот методов, использовать разное количество и типы параметров...
В общем, везде свои недостатки.)
Любая визуальная компонента любой системы по определению является непереносимой. Т.к. класс окна от борланда ты всё равно не сможешь использовать на msvs или qt. Хотя для переносимости я бы всё равно использовал транзитную обезличенную передачу: в виде void* передавал бы указатель на экземпляр и указатель на метод, а для того, чтобы обезличенные данные превратить в типизированные, завёл бы третий параметр, куда бы передал указатель на статический метод класса, внутри которого типизировал бы два обезличенных указателя. Этот вариант куда более удобен в использовании, чем технологии, требующие реализации воспомогательного класса.

Цитата Сообщение от Deviaphan Посмотреть сообщение
Нет. Нужно два виртуальных метода в функторе.
Два виртуальных метода в функторе нужно для того, чтобы передавать в BackBox два указателя, а не для того, чтобы вызывать раздельно два метода. Хотя это уже технические детали
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
18.04.2011, 07:58
Evg, наследование предназначено для копирожания дефолта, перекрытие членов предка - для того, чтоб в потомке сделать свой отличающийся дефолт, а если тебе каждый раз нужны другие дейтсвия, то или на каждый случай делай своего потмока, или выбрось к чёрту это долбаное наследование и делай через указатели. Зачем смешивать?
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
18.04.2011, 08:06
Цитата Сообщение от taras atavin Посмотреть сообщение
наследование предназначено для копирожания дефолта
Ничего подобного.
Где тут дефолт?
C++
1
2
3
4
5
6
class IX
{ 
public: 
    virtual void Fx1() = 0; 
    virtual void Fx2() = 0; 
};
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
18.04.2011, 08:15
А разве эти члены наследуются? Здесь то как раз не надо Страуструпом быть, чтоб увидеть гарантирвоанное перекрытие. Причём, в каждом конкретном потомке оно будет всегда одно и тоже.
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
18.04.2011, 08:30
Цитата Сообщение от taras atavin Посмотреть сообщение
чтоб увидеть гарантирвоанное перекрытие
Цитата Сообщение от taras atavin Посмотреть сообщение
а если тебе каждый раз нужны другие дейтсвия, то или на каждый случай делай своего потмока, или выбрось к чёрту это долбаное наследование и делай через указатели.
Я только об этом... как бы...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.04.2011, 08:30

Как сделать функцию от указателя на класс и указателя на метод?
Не получается сделать функцию, параметрами которой являются указатель на класс и на метод. Обращаться к классу нужно именно по указателю,...

Переопределение виртуального метода
Нужно написать виртуальный метод в родительском классе , который находит площадь круга. Затем переопределить этот виртуальный метод в...

переопределение виртуального метода
Существует родитель-класс TEditField = class(TObject) protected procedure ProcTextOut(Letter:Char; Color:TColor; BgColor:...

Ошибка создания виртуального метода?
Здравствуйте, хочу сделать так что бы программа(на андроид) рисовала по заданным координатам, но столкнулся со следующей ошибкой: ...

Реализовать перегрузку виртуального метода
В класе class1 реализован открытый виртуальный метод деление двух чисел "a" и "b". Не внося изменений в class1, реализовать метод с тем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
46
Ответ Создать тему
Новые блоги и статьи
сукцессия 14. Обновленная схема модели
anaschu 28.06.2026
ГЛОБАЛЬНАЯ ОПИСАТЕЛЬНАЯ СПЕЦИФИКАЦИЯ ЭКОСИСТЕМНОЙ МОДЕЛИ «SOIL CHEMISTRY & MYCORRHIZA 2. 0» https:/ / ibb. co/ NnkGpfMd Представленная интегрированная схема описывает непрерывную нелинейную. . .
сукцессия 13. Питон модель трехзонного мицелия, пока что в основном арбускулярного
anaschu 28.06.2026
## Разработка агентной модели микоризной сукцессии: от выявления артефактов к созданию комплексной системы ### Аннотация Представлено исследование по разработке агентной модели микоризной. . .
сукцессия 12. краткий список проверок модели перед запуском.
anaschu 27.06.2026
Скрытые отказы в моделях систем динамики (SD-models) экологических систем: два случая из практики Контекст Разбирался прототип модели систем динамики (SD-модели) микоризной сукцессии: пять. . .
Сукцессия 11. Проверка орудий перед войной: разработка через тестирование
anaschu 27.06.2026
Как не дать модели соврать самой себе: проверки для симуляции микоризной сукцессии Введение Когда вы строите математическую модель живой системы — грибов, растений, почвы — главная опасность. . .
10 сукцессия. Питон код войны грибов и растений
anaschu 27.06.2026
import numpy as np class PlantAgent: def __init__(self, name, strategy, initial_biomass): self. name = name self. strategy = strategy # "greedy" (широколиственные) или. . .
сукцессия 9. Математика подлости: как растения предали грибных друзей
anaschu 27.06.2026
Статья 2. Глобальная фосфорная война: эволюционно-экономические механизмы распределения биомов Земли Введение: Экологический рынок как игра с нулевой суммой Традиционная экология долгое время. . .
сукцессия 8. Как я спорил с ИИ, которые - агенты растений и ненавистники грибов!
anaschu 27.06.2026
Статья 1. Хроники грибного восстания: как Сократов диалог разрушил академические догмы ИИ Введение: Синдром «цифрового учебника» Современные большие языковые модели (LLM) обладают колоссальным. . .
Главный вопрос моделирования сукцессии
anaschu 27.06.2026
главный вопрос. Если эктомикориза лучше добывает недоступный фосфор. И ее масса максимальна из всех. А широколиственный лес тоже имеет самую крутую биомассу. То почему не возникло их симбиоза? Это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru