Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/21: Рейтинг темы: голосов - 21, средняя оценка - 4.76
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2

Вызов виртуальной функции, определённой в дочернем классе, через указатель на базовый класс

01.10.2018, 03:48. Показов 4071. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как вызвать виртуальную функцию, определённую в дочернем классе, через указатель на базовый класс?
Совершенно точно известно, что на момент вызова функции указатель содержит адрес объекта дочернего класса, для которого определена данная функция. Для базового класса функция не определена. И не может быть определена даже как чисто виртуальная. Явное приведение типа указателя не проходит, поскольку реальный тип объекта может варьироваться.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.10.2018, 03:48
Ответы с готовыми решениями:

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

Вызов метода производного класса через указатель на базовый класс
Всем привет ! Подскажите почему , при выполнении строки 45 я получаю ошибку ? А именно при выполнении выражения c->fnz() ...

Имеется базовый класс с некоторым событием, как вызвать это событие в дочернем классе?
Братцы, что то я отморозился, помогите разобраться с концепцией... Суть проблемы, имеется базовый класс с некоторым событием, как вызвать...

14
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
01.10.2018, 05:33
Цитата Сообщение от L0M Посмотреть сообщение
Совершенно точно известно, что на момент вызова функции указатель содержит адрес объекта дочернего класса, для которого определена данная функция. Для базового класса функция не определена. И не может быть определена даже как чисто виртуальная. Явное приведение типа указателя не проходит, поскольку реальный тип объекта может варьироваться.
1) Сделать дочерний класс с виртуальной функцией, назвать базовым, все остальное наследовать от этого дочернего класса.
2) Если стоит задача сделать все Си-стайл, то поместить в базовый класс указатель на нужную функцию.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,218
01.10.2018, 05:53
Цитата Сообщение от L0M Посмотреть сообщение
Явное приведение типа указателя не проходит, поскольку реальный тип объекта может варьироваться.
В такой ситуации - никак.
0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,532
Записей в блоге: 1
01.10.2018, 06:36
Цитата Сообщение от L0M Посмотреть сообщение
Для базового класса функция не определена. И не может быть определена даже как чисто виртуальная.
тогда какая вообще нам разница, виртуальная эта функция в дочернем классе или нет?
Базовый класс априори не знает и не должен знать, что там от него ещё унаследовано.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
01.10.2018, 07:16
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В такой ситуации - никак.
RTTI?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.10.2018, 11:48
Цитата Сообщение от L0M Посмотреть сообщение
Для базового класса функция не определена. И не может быть определена даже как чисто виртуальная.
никак.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
01.10.2018, 14:27  [ТС]
Цитата Сообщение от avgoor Посмотреть сообщение
RTTI?
Я думал на тему RTTI. Вот если бы можно было написать что-то типа
C++
1
2
BaseClass *object_pointer = ...;
dynamic_cast<typeid(object_pointer)>(object_pointer)->deriv_method();
тогда проблема была бы решена.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
01.10.2018, 14:31
Цитата Сообщение от avgoor Посмотреть сообщение
RTTI?
RTTI не работает без хоть одного виртуального метода в базовом классе. А ТС класть виртуальные методы в базовый класс не хочет.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
01.10.2018, 14:31  [ТС]
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
тогда какая вообще нам разница, виртуальная эта функция в дочернем классе или нет?
Разница в наличии таблицы виртуальных функций.
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
01.10.2018, 14:37
Лучший ответ Сообщение было отмечено L0M как решение

Решение

Цитата Сообщение от L0M Посмотреть сообщение
Для базового класса функция не определена.
Пусть наследники подмешивают эту функцию из другого абстрактного класса:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//g++  5.4.0
 
#include <iostream>
 
 
 
struct Base
{
    virtual ~Base() {}
};
 
 
 
struct AdvancedInterface
{
    virtual void foo() = 0;
    virtual ~AdvancedInterface() {}
};
 
 
struct FDerived: Base
{
};
 
 
struct SDerived: Base, AdvancedInterface
{
    virtual void foo() { std::cout << "SDerived::foo" << std::endl; }
};
 
 
int main()
{
    Base * p1 = new FDerived();
    Base * p2 = new SDerived();
    
    if (AdvancedInterface * p = dynamic_cast<AdvancedInterface*>(p1)) {
        p->foo();
    } else {
        std::cout << "p1 wrong type" << std::endl;
    }
        
    if (AdvancedInterface * p = dynamic_cast<AdvancedInterface*>(p2)) {
        p->foo();
    } else {
        std::cout << "p2 wrong type" << std::endl;
    }
    
    delete p1;
    delete p2;
}
http://rextester.com/QNAD84071
1
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,532
Записей в блоге: 1
01.10.2018, 14:43
Цитата Сообщение от L0M Посмотреть сообщение
Разница в наличии таблицы виртуальных функций.
а у этого наследника базового класса есть ещё какие-то потомки что ли? Ну, для которых эта таблица будет иметь смысл?
Чё думать об этой таблице, если её скорее всего вообще нет из-за отсутствия у класса потомков с виртуальными функциями.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
01.10.2018, 14:55  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
RTTI не работает без хоть одного виртуального метода в базовом классе.
Базовый класс имеет, как минимум, виртуальный деструктор. Извините, не написал сразу.
Цитата Сообщение от Renji Посмотреть сообщение
А ТС класть виртуальные методы в базовый класс не хочет.
Да ТС-то с удовольствием положил бы, только не получается.
Если в двух словах, то есть базовый класс-пустышка (фактически), и куча производных от него классов (без последующего наследования, по крайней мере, пока). Увязать эти классы, даже с использованием виртуального наследования, в перпендикулярную иерархию не получается.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
01.10.2018, 14:55
Мне кажется стоит просто остановиться, задать самому себе вопрос "а не херню ли я делаю", ответить на него и переписать этот участок кода.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
01.10.2018, 18:31
L0M, По сути, вы хотите паттерн visitor. В вашем случае нужно каждый наследник каким либо образом "зарегистрировать" в нем. Например, используя map<type_index, std::function<void(base)> пихая туда лямбду:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Base { public: virtual ~Base() {} };
class Derived1 : public Base { public: void foo() { std::cout << "derived1" << std::endl; } };
class Derived2 : public Base { public: void foo() { std::cout << "derived2" << std::endl; } };
 
int main()
{
    std::map < std::type_index, std::function<void(Base*)>> m;
 
    Derived1 d1;
    Derived2 d2;
 
    m[typeid(d1)] = [](Base* b)  { static_cast<Derived1*>(b)->foo(); };
    m[typeid(d2)] = [](Base* b)  { static_cast<Derived2*>(b)->foo(); };
 
 
    Base* b1 = &d1;
    Base* b2 = &d2;
 
    m[typeid(*b1)](b1);
    m[typeid(*b2)](b2);
}
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
07.10.2018, 03:48  [ТС]
Спасибо всем за ответы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.10.2018, 03:48
Помогаю со студенческими работами здесь

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

Указатель на базовый класс и дружественные функции
Здравствуйте. У меня есть базовый класс Number-простое целое число типа long int. В классе имеется 2 дружественных функции, перегрузка...

Создание объекта через указатель на базовый абстрактный класс
Есть абстрактный класс, от него наследуется 3 класса. В программе предусмотрено создание нового объекта(добавление клиента страховой...

Передача в контейнер объекта через указатель на базовый класс
Передаю в stl контейнер list указатель на производный класс, предварительно приведя его к типу производного класса - программа вылетает.В...

Запись объекта в файл через указатель на базовый класс
Можно ли при помощи write как-нибудь записать массив объектов производных классов в файл, используя для обращения к ним указатель на...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 09.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru