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

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

10.10.2015, 20:12. Показов 1595. Ответов 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
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru