Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Виртуальная таблица 
:(
    Опции темы
cppGhost
Дата 24.2.2016, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 24.4.2013

Репутация: нет
Всего: нет



День добрый
Код

struct A
{
    virtual void func() {};
};

struct B : public A
{
    void func() {};
    virtaul void funcB() {};
};

void main()
{
    B *b = new B();
    A *a = dynamic_cast<A*>(b);
    a->funcB();                                       // тут понятное дело ошибка

Так вот, когда мы приводим "b" к "а". Ведь в "а" , грубо говоря, находится указатель на виртуальную таблицу от класса "В". Иначе как бы мы вызывали виртуальные методы.
Но при вызове " a->funcB();" мы получаем ошибку, хотя он в этой таблице ведь тоже есть. Так в чём причина?
PM MAIL   Вверх
xvr
Дата 24.2.2016, 16:02 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(cppGhost @  24.2.2016,  15:25 Найти цитируемый пост)
Так в чём причина?

Причина в том, что в классе A нет виртуальной функции funcB. И то, что класс B положил ее адрес в таблицу виртуальных методов, никак не повлияет на класс A - он не знает, что лежит в таблице методов дальше func. Для него это все мусор.

PM MAIL   Вверх
vvm
Дата 25.2.2016, 10:34 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Добавляем funcB() в struct A

Код

#include <iostream>

using namespace std;

struct A
{
    virtual void func() {};
    virtual void funcB() {}; // добавили funcB()
};

struct B : public A
{
    void func() {};
    virtual void funcB() {};
};
int main()
{

    B *b = new B();
    A *a = dynamic_cast<A*>(b);
    a->funcB();

    return 0;
}



Этот ответ добавлен с нового Винграда - http://vingrad.com
  Вверх
volatile
Дата 25.2.2016, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(vvm @  25.2.2016,  10:34 Найти цитируемый пост)
A *a = dynamic_cast<A*>(b);

ну и зачем здесь dynamic_cast ?

dynamic_cast вообще редко когда реально нужен, и каждое его появление должно говорить о том, что здесь вероятно что-то не так...
Приведение же к базовуму типу - это самое заурядное явление, и dynamic_cast здесь не нужен


PM MAIL   Вверх
cppGhost
Дата 25.2.2016, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 24.4.2013

Репутация: нет
Всего: нет



xvr, то есть получается, что я просто в кучу смешал два разных правила, так? одно дело знает ли класс A обо всех членах класс В. А другое дело реализация полиморфизма через виртуальную таблицу.

xvm, спасибо. про это я в курсе, пример был для наглядности))

volatile, в целом я понимаю, что когда мы так приводим, то хотим сгладить некоторые шереховатости проектирования. Но с другой стороны, а если вот надо привести от В к А, то неужели нужно писать в стиле обычного С ?
PM MAIL   Вверх
xvr
Дата 25.2.2016, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(cppGhost @  25.2.2016,  13:47 Найти цитируемый пост)
xvr, то есть получается, что я просто в кучу смешал два разных правила, так?

Да. С++ язык со статической (compile time) типизацией - все, что известно о классе, должно быть известно на момент компиляции его описания. Никакой информации о наследниках базовый класс не имеет.

Если нужна динамическая типизация - переходите на языки типа JavaScript (и прочие интерпретируемые). В нем объект не ограничен методами, которые были на момент описания (описания вообще может и не быть  smile ), а наличие тех или иных методов и членов выясняется в момент вызова абсолютно динамически  smile

Добавлено через 2 минуты и 3 секунды
Цитата(cppGhost @  25.2.2016,  13:47 Найти цитируемый пост)
Но с другой стороны, а если вот надо привести от В к А, то неужели нужно писать в стиле обычного С ? 

Тут вообще ничего приводить не надо. Надо будет если попробовать привести от A* к B*, и скорее всего достаточно будет static_cast<B*>

PM MAIL   Вверх
volatile
Дата 25.2.2016, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(cppGhost @  25.2.2016,  13:47 Найти цитируемый пост)
а если вот надо привести от В к А, то неужели нужно писать в стиле обычного С ? 

я нигде не говорил что нужно приводить в стиле С
просто в конкретно этом примере приведение вообще не нужно

Цитата(cppGhost @  24.2.2016,  15:25 Найти цитируемый пост)
A *a = dynamic_cast<A*>(b);
A *a = b;


Добавлено через 3 минуты и 34 секунды
а вот если нужно обратное приведение - это сигнал того, что вероятно что-то не так в программе.
(в прочем исключения конечно есть)

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0805 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.