Ошибка компоновщика g ++ - typeinfo, но не vtable - PullRequest
1 голос
/ 26 мая 2010

Я знаю, что стандартный ответ для ошибки компоновщика об отсутствии typeinfo обычно также включает vtable и некоторую виртуальную функцию, которую я забыл определить.

Я совершенно уверен, что на этот раз ситуация не такая.

Вот ошибка:

UI.o: в функции boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::Resource::GroupByState>(boost::shared_ptr<Graphics::Resource::GroupByState> const&, boost::detail::dynamic_cast_tag)': UI.cpp:(.text._ZN5boost10shared_ptrIN8Graphics7Widgets9WidgetSetEEC1INS1_8Resource12GroupByStateEEERKNS0_IT_EENS_6detail16dynamic_cast_tagE[boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::Resource::GroupByState>(boost::shared_ptr<Graphics::Resource::GroupByState> const&, boost::detail::dynamic_cast_tag)]+0x30): undefined reference to typeinfo для графики :: Widgets :: WidgetSet '

Запуск c ++ filal для отвратительного искаженного имени показывает, что он действительно просматривает .boost :: shared_ptr :: shared_ptr (boost :: shared_ptr const &, boost :: detail :: dynamic_cast_tag)

Иерархия наследования выглядит примерно так:

class AbstractGroup
{
   public:
      virtual ~AbstractGroup();
      typedef boost::shared_ptr<AbstractGroup> Ptr;
      ...
};

class WidgetSet : public AbstractGroup
{
    public:
       virtual ~WidgetSet();
       typedef boost::shared_ptr<WidgetSet> Ptr;
       ...
};

class GroupByState : public AbstractGroup
{
    public:
       virtual ~GroupByState();
       ...
};

Тогда есть это:

class UI : public GroupByState
{
    public:
       virtual ~UI();
       ...
       void LoadWidgets( GroupByState::Ptr resource );
       ...
};

Тогда оригинальная реализация:

void UI::LoadWidgets( GroupByState::Ptr resource )
{
   WidgetSet::Ptr tmp( boost::dynamic_pointer_cast< WidgetSet >(resource) );
   if( tmp )
   {
       ...
   }
}

Глупая ошибка с моей стороны (попытка привести к братскому классу с общим родителем), даже если эта ошибка не совсем понятна.

Изменение на это:

void UI::LoadWidgets( AbstractGroup::Ptr resource )
{
   WidgetSet::Ptr tmp( boost::dynamic_pointer_cast< WidgetSet >(resource) );
   if( tmp )
   {
       ...
   }
}

(что я вполне уверен, что я действительно хотел сделать) оставил мне с очень похожей ошибкой:

UI.o: в функции boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::_Drawer::Group>(boost::shared_ptr<Graphics::_Drawer::Group> const&, boost::detail::dynamic_cast_tag)': UI.cpp:(.text._ZN5boost10shared_ptrIN8Graphics7Widgets9WidgetSetEEC1INS1_7_Drawer5GroupEEERKNS0_IT_EENS_6detail16dynamic_cast_tagE[boost::shared_ptr<Graphics::Widgets::WidgetSet>::shared_ptr<Graphics::_Drawer::Group>(boost::shared_ptr<Graphics::_Drawer::Group> const&, boost::detail::dynamic_cast_tag)]+0x30): undefined reference to typeinfo for Graphics :: Widgets :: WidgetSet ' collect2: ld вернул 1 статус выхода

dynamic_cast_tag - это просто пустая структура в boost / shared_ptr.hpp. Это просто предположение, что boost может иметь какое-либо отношение к ошибке.

Передача WidgetSet :: Ptr полностью устраняет необходимость в приведении, и он прекрасно работает (вот почему я думаю, что здесь происходит больше, чем стандартный ответ на этот вопрос).

Очевидно, я обрезал много деталей, которые могут быть важны. Мой следующий шаг - сократить его до мельчайшего примера, который не удается построить, но я решил, что попробую ленивый выход и сначала нанесу удар.

ТИА!

РЕДАКТИРОВАТЬ: Показать еще некоторые детали, которые люди прокомментировали

Ответы [ 2 ]

1 голос
/ 26 мая 2010

Не видя всего вашего класса AbstractGroup, трудно быть уверенным, но, похоже, у вас нет виртуальных функций в иерархии классов. Попробуйте определить виртуальный деструктор в AbstractGroup (подойдет даже встроенный) и посмотрите, имеет ли это значение. Без единой виртуальной функции нет vtable и, следовательно, нет места для зависания данных typeinfo.

0 голосов
/ 26 мая 2010

Члены частные? Если это так, попробуйте добавить protected: перед членами ваших классов.

class AbstractGroup
{
protected:
   typedef boost::shared_ptr<AbstractGroup> Ptr;
   ...
};


class WidgetSet : public AbstractGroup
{
protected:
    typedef boost::shared_ptr<WidgetSet> Ptr;
  ...
};

Еще одна вещь появилась после возвращения в ваш пример кода. Похоже, вы пытаетесь использовать полиморфизм. Единственная проблема заключается в том, что вы динамически приводите объект общего указателя к WidgetSet. После прочтения некоторой документации я считаю, что вам следует написать resource.get_pointer(), поскольку вы хотите привести указатель в объект shared_ptr, а не сам объект shared_ptr. Я не очень знаком с бустом, поэтому, пожалуйста, скажите, если это имеет смысл!

...