Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
1

Безопасен ли static_cast для полиморфных классов?

25.04.2017, 17:32. Показов 938. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
добрый день.
проблема возникла из ниоткуда, по сути.
просто в одном проекте используется boost.variant, для каста, соответственно, boost::get, но суть в том, что каждый экземпляр класса содержит тег, по которому можно определить тип variant'a.
то есть как-то так:
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <boost/variant.hpp>
 
enum Type
{
    Int,
    Double,
    Char
};
 
struct IntT
{
    int n;
};
 
struct DoubleT
{
    double d;
};
 
struct CharT
{
    char c;
};
 
using VariantBody = boost::variant<IntT, DoubleT, CharT>;
 
struct Example
{
    Type mType;
    VariantBody mBody;
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    Example ex;
    
    {
        ex.mType = Type::Int;
        boost::get<IntT>(ex.mBody);
    }
    
    if (ex.mType == Type::Int)
    {
        const auto & body = boost::get<IntT>(ex.mBody).n = 10;
        std::cout << "body: " << body << "\n";
    }
}

я подумал-подумал и понял, что в каком-то там варианте нет смысла, можно воспользоваться полиморфизмом и static_cast'ом и жить спокойно, сделал прототип и думаю его протолкнуть.
вопрос вообще в том, будет ли это быстрее?
в реализации boost.variant нашёл std::addressof, что означает, что какая-то часть вычислений перенесена в рантайм. плюс там кидается экзепшон в boost::get, ну и проверки происходят всякие, медленно(я думаю), в общем.
прототип:
Кликните здесь для просмотра всего текста
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
#include <iostream>
 
enum Type
{
    Null,
    Int,
    Double,
    Char
};
 
struct BaseDummy
{
    BaseDummy(Type type = Type::Null)
        :
        mType(type)
    {}
 
    virtual ~BaseDummy() {}
    
    Type getType() const
    {
        return mType;
    }
    
protected:
    Type mType;
};
 
struct IntT : public BaseDummy
{
    IntT()
        :
        BaseDummy(Type::Int),
        n(0)
    {}
 
    int n;
};
 
struct DoubleT : public BaseDummy
{
    DoubleT()
        :
        BaseDummy(Type::Double),
        d(0)
    {}
 
    double d;
};
 
struct CharT : public BaseDummy
{
    CharT()
        :
        BaseDummy(Type::Char),
        c(0)
    {}
 
    char c;
};
 
struct Example
{
    BaseDummy mBody;
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    Example ex;
    
    {
        ex.mBody = IntT();
    }
    
    if (ex.mBody.getType() == Type::Int)
    {
        const auto & body = static_cast<IntT&>(ex.mBody).n = 10;
        std::cout << "body: " << body << "\n";
    }
}

что думаете, какие у этого есть недостатки/достоинства?
может быть я где-то пропустил UB?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.04.2017, 17:32
Ответы с готовыми решениями:

Операция приведение типов для полиморфных классов
Задание: Для двух полиморфных классов проверить законность выполнения заданной операции приведения...

Разработка полиморфных классов для обработки банковских счетов
Разработать полиморфные классы для обработки счетов банка . Первый класс является абстракцией...

Shared_ptr для полиморфных объектов
Началось всё с того, что понадобилось хранить указатели на полиморфные объекты, якобы объект...

Даёт ли вендор гарантию на разгон? Безопасен ли разгон при применении фирменной утилиты для разгона?
Даёт ли вендор гарантию на разгон при использовании его фирменной утилиты для разгона? И безопасен...

4
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
25.04.2017, 17:51 2
Цитата Сообщение от GbaLog- Посмотреть сообщение
что думаете, какие у этого есть недостатки/достоинства?
Я не думаю, что будет особая разница между обращением к таблице виртуальных функций или к вручную созданной переменной. Могу посоветовать вручную протестировать оба способа и посмотреть, что же там в ассемблере получается...

Добавлено через 6 минут
UPD: dynamic_cast будет дороже, что-то VS2017 не особо умеет его оптимизировать.
0
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
25.04.2017, 18:04 3
Какое-то сплошное извращение. Но, будем считать, что так надо.
В теории, static_cast должен быть быстрее, т.к. Boost.Variant использует RTTI, а это дороговато. В любом случае, нужны тесты, конкретные цифры скажут больше, чем "а вот я думаю".
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
25.04.2017, 19:53  [ТС] 4
Цитата Сообщение от MrGluck Посмотреть сообщение
Какое-то сплошное извращение.
извращение-то извращение, но скорость очень важна, в данном случае.
что-то поискал бенчмарки, но там то variant побеждает, то полиморфизм.
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Я не думаю, что будет особая разница между обращением к таблице виртуальных функций или к вручную созданной переменной.
и в каком случае будет обращение к vtable?

завтра свой бенчмарк напишу, короче.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
25.04.2017, 20:35 5
Цитата Сообщение от GbaLog- Посмотреть сообщение
и в каком случае будет обращение к vtable?
Конечно все зависит от реализации, но зачастую dynamic_cast работает через обращение к vtable. Например, при использовании dynamic_cast компилятор требует наличия виртуальных функций, нет функций - нет таблицы виртуальных функций.
Ну и как видно из результатов моего компилятора, dynamic_cast преобразуется в вызов какой-то функции, когда как static_cast - в копирование указателя со смещением.
Так что static_cast получше будет.
0
25.04.2017, 20:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.04.2017, 20:35
Помогаю со студенческими работами здесь

Программирование полиморфных методов
Задание: Создать абстрактный базовый класс Body (тело) с виртуальными функциями вычисления площади...

динамическое приведение полиморфных объектов
Есть иерархия классов Shape: 1. TwoDimensionalShape: circle, triangle, rectangle 2....

Безопасен ли 4G Модем?
Доброго времени суток! Вопрос в сфере безопасности использования 4G модема. Прошу писать...

Безопасен ли Edge?
Добрый вечер! Учитывая мой негативный опыт с IE, с опаской смотрю в сторону ультрасовременного...

Как правильно использовать operator= при наследовании в полиморфных и неполиморфных классах
Доброго времени суток! Изучаю книгу С. Прата &quot;Язык программирования C++. Лекции и упражнения.&quot;...

Насколько безопасен WebMoney
Интересует такой вопрос. Известны ли случаи &quot;угона&quot; средств с кошельков, привязанных к телефону...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru