Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Виртуальная таблица


Автор: cppGhost 24.2.2016, 15:25
День добрый
Код

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();" мы получаем ошибку, хотя он в этой таблице ведь тоже есть. Так в чём причина?

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

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

Автор: vvm 25.2.2016, 10:34
Добавляем 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://ru.vingrad.com/Virtualnaya-tablitsa-id56cda195ae20154b768b4567#findElement_E7045_56ceae7eae20151a51b26235_0

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

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

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


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

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

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

Автор: xvr 25.2.2016, 14:19
Цитата(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*>

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

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

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


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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)