Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 21.11.2013
Сообщений: 13

Как определить тип объекта из таблицы виртуальных методов?

10.10.2015, 20:12. Показов 1621. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как можно определить тип объекта из таблицы виртуальных методов? Необходимо сравнить типы, не используя typeid, а также dynamic_cast.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.10.2015, 20:12
Ответы с готовыми решениями:

Виртуальные функции, таблицы виртуальных методов, как они работают?
подскажите пожалуйста,где лучше посмотреть про начинку виртуальных функций,т.е. про таблицы виртуальных методов и как они работают. Заранее...

Что такое порядок инициализации таблицы виртуальных методов?
Что-то я не переварил это.

Сравнение 2 объектов, через адрес таблицы виртуальных методов
Есть функция принимающая на вход 2 указателя на объекты (класс скорее всего является интерфейсом, ну у него есть виртуальные функции). Так...

6
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
10.10.2015, 21:21
Цитата Сообщение от Firsto Посмотреть сообщение
Как можно определить тип объекта из таблицы виртуальных методов? Необходимо сравнить типы, не используя typeid, а также dynamic_cast.
никак.
0
0 / 0 / 0
Регистрация: 21.11.2013
Сообщений: 13
26.10.2015, 10:20  [ТС]
Всё же сравнить типы удалось (но не определить их).

C++
1
2
3
4
5
6
7
8
9
typedef void (*FunctionPtr)();
 
bool check_equals(Ex const *left, Ex const *right)
{
    FunctionPtr* vtable1 = *(FunctionPtr**)(&left);
    FunctionPtr* vtable2 = *(FunctionPtr**)(&right);
    bool b = (size_t*)vtable1[0] == (size_t*)vtable2[0];
    return b;
}
Принимает на вход два указателя на базовый класс (Ex), и возвращает true, если оба указателя указывают на самом деле на объекты одного и того же класса, и false в противном случае.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
26.10.2015, 10:34
Это как использование недокументированных функций Windows - вроде бы и работает, но без гарантий.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
26.10.2015, 12:55
Да, нет гарантий, что VPTR будет по нулевому смещению, нет даже гарантий, что он вообще будет, т.к. реализация позднего связывания полностью на совести разработчиков компиляторов.
0
0 / 0 / 0
Регистрация: 21.11.2013
Сообщений: 13
26.10.2015, 13:27  [ТС]
С точки зрения стандарта это так, но тем не менее на различных версиях компиляторов g++/clang++/msvc работает.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.11.2015, 01:14
Цитата Сообщение от Firsto Посмотреть сообщение
С точки зрения стандарта это так, но тем не менее на различных версиях компиляторов g++/clang++/msvc работает.
это не соответствует вашей задаче.

вот это извращение:
C++
1
2
3
4
5
6
7
bool check_equals(Ex const *left, Ex const *right)
{
    FunctionPtr* vtable1 = *(FunctionPtr**)(&left);
    FunctionPtr* vtable2 = *(FunctionPtr**)(&right);
    bool b = (size_t*)vtable1[0] == (size_t*)vtable2[0];
    return b;
}
по уму делается так:

C++
1
2
3
4
bool check_equals(Ex const *left, Ex const *right)
{
    return typeid(*left) == typeid(*right);
}
и все стандартно и портируемо.

но вы ж хотите поиметь фактический тип объекта.

возможно вам поможет type-erasure.

история о том, как можно клонировать объекты,
у которых нет в интерфейсе виртуального метода clone


http://rextester.com/BHSQ1979

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <memory>
 
// --- отсутствует метод клонирования
struct IBase
{
    virtual ~IBase(){}
    virtual const char* GetName()const = 0;
    void AboutMe() { std::cout << GetName()<<'\n'; }
};
 
struct Der: IBase 
{
    Der()
    {
        std::cout<<"[ctor] "<< GetName()<<'\n'; 
    }
    
    Der(const Der& rhs)
    {
        std::cout<<"[copy] "<< GetName()<<'\n'; 
    }
    
    const char* GetName()const { return "my name is Der"; }
};
struct Bar: IBase 
{
    Bar()
    {
        std::cout<<"[ctor] "<< GetName()<<'\n'; 
    }
    
    Bar(const Bar& rhs)
    {
        std::cout<<"[copy] "<< GetName()<<'\n'; 
    }
    
    const char* GetName()const { return "my name is Der"; }
};
 
// --- тем не менее, мы хотим иметь возможность
// клонировать наследников
//
// для этого будем использовать специальный враппер
// который используя паттерн type-erasure
// сможет "запоминать" фактический тип захваченного им ресурса
// и выполнять различные действия.
//
// в частности становится возможным выполнить клонирование объектов
// независимо от того, 
// есть ли у них метод clone в базовом интерфейсе
 
 
template<class T> struct wrapper
{
    typedef std::shared_ptr<IBase>
        res;
    
    struct ihelp
    {
        virtual res clone(const res& obj)const = 0;
    };
    
    
    // не должен иметь данных-членов
    // но для упрощения кода все проверки удалены
    template<class U> struct help
    {
        virtual res clone(const res& obj)const 
        {
            // параметр U совпадает с типом ресурса
            // поэтому статический каст от базы к наследнику 
            // гарантированно возможен
            const auto& der 
                = std::static_pointer_cast<U>(obj);
            
            return std::make_shared<U>(*der);
        }
    };
    
    template<class U, class... Args>
    void emplace(Args&& ...args)
    {
        // при захвате ресурса
        // мы не только конструируем сам ресурс
        m_res = std::make_shared<U>( std::forward<Args>(args)... );
        
        // но и запоминаем его фактический тип
        new (m_help) help<U>;
    }
    
    T* operator->() { return m_res.get(); }
    
    res copy()const
    {
        const auto* cloner 
            = reinterpret_cast<const ihelp*>(m_help);
        return cloner->clone(m_res);
    }
    
    res m_res;
    
    char m_help[ sizeof(ihelp) ];
    
};
 
void test(const wrapper<IBase>& obj)
{
    // IBase не умеет клонирование
    // однако wrapper запомнил 
    // фактический тип ресурса
    // поэтому может запустить конструктор копии наследника
    auto copy = obj.copy();
    copy->AboutMe();
}
 
int main()
{
    std::cout << "Hello, world!\n";
    
    wrapper<IBase> der;
    
    // захватываем ресурс
    // враппер запоминает фактический тип ресурса 
    // при помощи специального хэлпера
    der.emplace<Der>();
    der->AboutMe();
 
    test(der);
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.11.2015, 01:14
Помогаю со студенческими работами здесь

Как определить тип объекта?
Как определить тип объекта arr3? alert(arr3.type)-не работает &lt;html&gt; &lt;script&gt; var n1=parseInt(prompt('Введите количество...

Как определить тип объекта?
Здравствуйте. У меня следующий вопрос: на форме расположено две группы фреймов, в каждой группе имена фреймов различаются только...

Как определить тип передаваемого объекта
Есть компонент с названием simpleOpenGlControl. Его нужно передать в функцию, но такое: public static void sphere(simpleOpenGlControl ...

Как избежать не нужной пустой реализации виртуальных методов в базовом классе?
Для наглядности: class BASE { public: BASE(); ~BASE(); virtual void Do();

Как определить тип Sender'a объекта при использовании динамически созданных объекитах
Есть динамически созданные объекты на форме: int counter=0; for(int i=1; i&lt;4; i++) { for(int j=1; j&lt;4; j++) { ...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru