2009-02-26 6 views
5

У меня есть базовый класс и производный класс. Каждый класс имеет файл .h и файл .cpp.dynamic_cast failed

Я делаю dynamic_cast объекта базового класса в производном классе в следующем коде:

ч файлы:

class Base 
{ 
    public: 
    Base(); 
    virtual ~Base(); 
}; 

class Derived : public Base 
{ 
    public: 
    Derived(){}; 
    void foo(); 
}; 

class Another 
{ 
    public: 
    Another(){}; 
    void bar(Base* pointerToBaseObject); 
}; 

CPP файлы:

Base::Base() 
{ 
    //do something.... 
} 
Base::~Base() 
{ 
    //do something.... 
} 
void Derived::foo() 
{ 
    Another a; 
    a.bar(this); 
} 
void Another::bar(Base* pointerToBaseObject) 
{ 
    dynamic_cast<Derived*>(pointerToBaseObject) 
} 

От какой-то странной причине , сбой каста (возвращает NULL). Однако кастинг преуспевает, если я перемещаю реализацию конструктора класса Derived из .h в файл .cpp.

Что может быть причиной этого?

Компилятор gcc 3.1, на Linux-SUSE. BTW, я вижу это поведение только на этой платформе, и тот же код отлично работает в Visual Studio.

+0

Может быть, это ошибка с GCC 3.1 работает? попробуйте параметр «-fdump-class-hierarchy» и посмотрите, создает ли он vtable для ваших двух классов. –

ответ

5

Код, как указано, не должен терпеть неудачу, если у вас есть виртуальная функция в базовом классе (как указано в ярлыке).

Но я считаю, что каждый текущий компилятор генерирует ошибку «Base class is not polymorphic», если вы этого не сделали, поэтому, вероятно, это не проблема.

Единственное, что я могу придумать, это то, что из-за какой-то странной ошибки все встает в очередь и не генерируется vtable. Но если вы поместите конструктор в файл C++, компилятор решит не встраивать все, инициируя создание виртуальной таблицы, заставляя ваш актер работать.

Но это очень дикая догадка, и я не думаю, что любой компилятор будет иметь такую ​​ошибку в нем (?)

Если вы хотите определенный ответ, разместить больше коды. И используется компилятор/платформа.

EDIT: Увидев обновленный код

Я думаю, вы должны по крайней мере Dérivé производный от базы;) (я полагаю, что это опечатка)

Но после просмотра кода, единственное, что я могу думать о заключается в том, что gcc (ошибочно) строит все и не создает vtable для Derived. Для чего это стоит, это отлично работает с gcc 4.0

3.1 уже более 7 лет ... если есть возможность обновить, я бы пошел на это.

7

У вас есть виртуальная функция в базе? Это не будет работать иначе. Если ничего другого, сделайте его dtor виртуальным.

Не знаю, был ли он уже задан другим парнем, который удалил его ответ, но я считаю, что это было нечто другое: вы делаете dynamic_cast из конструктора баз? Если это так, это не сработает. Компилятор будет думать, что Base - это самый производный тип, похожий на то, когда вы вызываете виртуальную функцию, и заканчивается тем, что вызывает версию Base.

+0

У меня есть виртуальные функции в базе. –

3

Сделайте виртуальный деструктор и поместите его (или, по крайней мере, один виртуальный метод) в файл .cpp.

Некоторые компиляторы (читайте: gcc) ищите первый экземпляр виртуального тела без встроенного метода и используйте его для определения места размещения таблицы виртуальных методов.Если у вас нет виртуальных методов с телами в файле .cpp, таблица виртуальных методов не создается.

У вас должен быть хотя бы один виртуальный метод для работы dynamic_cast. Динамический листинг использует таблицу для определения информации о типе, и таблица не создается, если нет виртуальных методов.

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

0

Вы делаете это в Visual C++? Я думаю, что вам нужно включить информацию о типе времени выполнения (RTTI) в настройке компилятора, чтобы это работало.

Пожалуйста, не плачьте, если я ошибаюсь. Прошло некоторое время с тех пор, как я использовал C++ !!!

0

При взгляде на ваш код я не вижу никакого наследования. Вы забыли это сделать? Производные не происходят ни от чего.

0

В коде, который вы опубликовали, Производный не является производным от базы.

Edit: FYI, модифицированный код хорошо с г ++ 3.4.5