Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
CEBEP
107 / 107 / 9
Регистрация: 21.03.2010
Сообщений: 445
#1

Приведение к типу-наследнику - C++

30.03.2014, 20:52. Просмотров 1460. Ответов 22
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
class A {
};
class B: public A {
    void foo() const { std::cout << "some is king of every fish"; }
};
int main() {
    A* pointer(new B);
    static_cast<B*>(static_cast<void*>(pointer))->foo();
    return 0;
}
Можите на пальцах объяснить, как, без каких бы то ни было проверок, без дополнительных вычислений на этапе выполнения вызвать метод foo класса B для объекта, указатель на который хранится, как указатель на А? Заранее спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.03.2014, 20:52
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Приведение к типу-наследнику (C++):

ООП. Динамическое приведение типа от родителя к наследнику - C++
Добрый день, коллеги. Проблема в следующем. Есть два библиотечных класса (xerces). 1) DOMElement class DOMElement : public DOMNode ...

Приведение к типу - C++
В чем разница? static_cast&lt;int&gt;(a); и (int)a

Приведение к базовому типу - C++
#include &lt;iostream&gt; using namespace std; class A{ public: virtual ~A() {} }; class B: public A{ };

Приведение void* указателя к типу - C++
struct tParamStruct { const char* Result; }; tParamStruct ParamStruct; void show(void *AdressPS) { // ????????

Приведение переменной к другому типу - C++
float a = (float)x; // старый стиль float b = static_cast&lt;float&gt;(y); // современный стиль разве по старому не удобнее? почему...

Приведение void* к типу указателя на структуру - C++
Тема обсуждалась здесь, но решения так и нет нормального Есть два (и более, хоть до 20) линейных списков и функция обхода списка В...

22
ValeryS
Модератор
6749 / 5158 / 493
Регистрация: 14.02.2011
Сообщений: 17,329
30.03.2014, 22:20 #16
Цитата Сообщение от CEBEP Посмотреть сообщение
или в виду имелось что-то другое?
ну вот я показывал
Цитата Сообщение от ValeryS Посмотреть сообщение
B* pointer =new B;
из B то к членам A проще достучатся, чем наоборот
0
DrOffset
7387 / 4464 / 1013
Регистрация: 30.01.2014
Сообщений: 7,317
30.03.2014, 22:28 #17
Цитата Сообщение от zss Посмотреть сообщение
Вы абсолютно не правы.
Это как раз область ведения reinterpret_cast.
Т.е. мы выполняем действие, которое противоречит представлениям компилятора.
Он ведь не знает, что указатель показывает на экземпляр производного класса,
а мы знаем! Поэтому такое действие с точки зрения программиста оправдано.
Я просто оставлю это здесь.

Цитата Сообщение от zss Посмотреть сообщение
В этом конкретном примере это работает. Однако я говорил про общий случай и про возможные последствия. Мы не знаем наверняка насколько сложная иерархия у ТС в проекте и какие будут в будущем use cases.

Добавлено через 4 минуты
CEBEP, в чем проблема завернуть static_cast в функцию? Другого относительно безопасного способа это сделать, да еще и без дополнительных проверок, все равно нет.
1
CEBEP
107 / 107 / 9
Регистрация: 21.03.2010
Сообщений: 445
30.03.2014, 22:31  [ТС] #18
Цитата Сообщение от ValeryS Посмотреть сообщение
ну вот я показывал
нашел. Да, в некоторых местах так делать удаётся, но синтаксически ещё более накладно... если вводить много вспомогательных строчек, код становится ещё менее читаемый чем при громоздких однострочных выражениях:
C++
1
2
3
4
5
6
7
8
9
void Renumbering::splitSideTest(size_t i) {
    VertexData::SplitSide s(static_cast<VertexData*>(static_cast<void*>(data.nodeData(i)))->getSide());
    for (Graph::NodeItem::const_iterator it(data.nodeItem(i).begin()), end(data.nodeItem(i).end()); it != end; ++it) {
        if (static_cast<VertexData*>(static_cast<void*>(data.nodeData(it->first)))->getSide() != s) {
            static_cast<VertexData*>(static_cast<void*>(data.nodeData(i)))->setSide(VertexData::Splitter);
            return;
        }
    }
}
вот пример такого завала... замечу, что во всех трёх случаях аргументами кастов являются разные величины, т. е. понадобилось бы три вспомогательных строки типа VertexData* pointer = (VertexData*) data.nodeData(i); которые сами по себе уже нагоняют тоску...

Добавлено через 2 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
в чем проблема завернуть static_cast в функцию?
Да, это вполне адекватное решение, но тут придётся пологаться на милость компилятора в том плане, что он как может заменить вызов функции на тело так и может организовать реальный вызов функции...
0
DrOffset
7387 / 4464 / 1013
Регистрация: 30.01.2014
Сообщений: 7,317
30.03.2014, 22:37 #19
Цитата Сообщение от CEBEP Посмотреть сообщение
Да, это вполне адекватное решение, но тут придётся пологаться на милость компилятора в том плане, что он как может заменить вызов функции на тело так и может организовать реальный вызов функции...
inline однострочник практически гарантированно будет встроен любым современным компилятором.

Добавлено через 2 минуты
CEBEP, спрошу еще раз: какая необходимость делать каст через void*?
0
CEBEP
107 / 107 / 9
Регистрация: 21.03.2010
Сообщений: 445
30.03.2014, 22:37  [ТС] #20
Цитата Сообщение от DrOffset Посмотреть сообщение
Я просто оставлю это здесь.
там же речь о множественном наследовании и приведении типов к базовым. тут не имеет места ни такой вид наследования не такая ориентация приведения...
0
DrOffset
7387 / 4464 / 1013
Регистрация: 30.01.2014
Сообщений: 7,317
30.03.2014, 22:41 #21
Цитата Сообщение от CEBEP Посмотреть сообщение
там же речь о множественном наследовании и приведении типов к базовым. тут не имеет места ни такой вид наследования не такая ориентация приведения...
Товарищ zss написал, что я абсолютно не прав. Эта ссылка пруф того, что я прав, т.к. я говорил про общий случай. И про то, что у reinterpret_cast нет в данной ситуации никаких преимуществ перед static_cast, зато появляются минусы, если появляется такой тип наследования.
0
CEBEP
107 / 107 / 9
Регистрация: 21.03.2010
Сообщений: 445
30.03.2014, 22:44  [ТС] #22
Цитата Сообщение от DrOffset Посмотреть сообщение
какая необходимость делать каст через void*
Интересно. Был уверен, что на static_cast<B*>(pointer) компилятор ругается... сейчас убедился, что это не так... Так намного легче, спасибо
0
DrOffset
7387 / 4464 / 1013
Регистрация: 30.01.2014
Сообщений: 7,317
30.03.2014, 22:54 #23
Цитата Сообщение от CEBEP Посмотреть сообщение
Так намного легче, спасибо
Именно. Я к этому вел с самого начала. Каст через void* к тому же обеспечит те же проблемы с множественным наследованием (пусть его нет в данном случае, но игнорировать этот факт нельзя), про которые я говорил. Каст через void* заблокирует способность static_cast вывести правильный адрес при преобразовании база->наследник, т.к. void* уже не несет информации о типе.

Добавлено через 4 минуты
CEBEP, есть целая техника, основанная на таком касте (база->наследник), может быть интересно на будущее.
1
30.03.2014, 22:54
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.03.2014, 22:54
Привет! Вот еще темы с ответами:

Приведение указателя на void к другому типу? - C++
в поиске смотрел - не помогло! Возникла проблемка: В книге сказано, что указателю на void можно присваивать все типы указателей без...

Приведение двух классов к типу друг друга - C++
Всем добрый день, Прошу вашей помощи с пониманием принципов работы приведения типов. Проблема следующая: class Sterling1502...

Приведение void указателя к определенному типу с сохранением результата - C++
Есть функция funс(void *pointer, char type) { ... } Нужно чтобы в данной функции этот указатель приводился к определенному типу...

Приведение одного парметра-типа к другому разыменованному парметру-типу (указателю) в шаблонах - C++
Здравствуйте! изучаю C++, и есть такой вопрос, можно ли при инстанцировании, допустим, шаблонной функции привести один параметр-тип к...


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

Или воспользуйтесь поиском по форуму:
23
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.