2010-05-25 5 views
1

Je sais que la réponse standard pour une erreur de lien sur typeinfo manquant implique également vtable et une fonction virtuelle que j'ai oublié de définir réellement.g ++ erreur de lien - typeinfo, mais pas vtable

Je suis assez certain que ce n'est pas la situation cette fois-ci.

est ici l'erreur:

UI.o: En fonction 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 pour des graphiques Widgets :: widgetset »

Exécution C++ filt sur le nom mutilée odieux montre qu'il est en fait à la recherche .Améliorez :: shared_ptr :: shared_ptr (boost :: shared_ptr const &, boost :: détail :: dynamic_cast_tag)

La hiérarchie d'héritage ressemble à quelque chose comme

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(); 
     ... 
}; 

Ensuite, il y a ceci:

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

Ensuite, la mise en œuvre originale:

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

erreur stupide de ma part (tente de jeter à une classe de frères et soeurs avec un parent commun), même si l'erreur est un peu de cryptique.

Changing à ceci:

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

(que je suis assez sûr est ce que je voulais dire à faire) m'a laissé avec une erreur très similaire:

UI.o: En fonction 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 pour Graphics :: Widgets :: WidgetSet ' collect2: ld a renvoyé 1 statut de sortie

dynamic_cast_tag est juste une structure vide dans boost/shared_ptr.hpp. C'est juste une supposition que boost pourrait avoir quelque chose à voir avec l'erreur. Passer dans un WidgetSet :: Ptr élimine totalement le besoin d'un cast, et il se construit bien (c'est pourquoi je pense qu'il y a plus de choses que la réponse standard pour cette question).

De toute évidence, je supprime beaucoup de détails qui pourraient être importants. Ma prochaine étape est de réduire au plus petit exemple qui ne parvient pas à construire, mais je me suis dit que j'essaierais la sortie paresseux et de prendre d'abord le coup ici.

TIA!

EDIT: Voir quelques détails que les gens ont formulé des observations au sujet

+0

ajouter à la réponse de @Drew Hall ci-dessous.dynamic_cast a besoin de RTTI qui est stocké dans vftable mais comme vous n'avez aucune méthode virtuelle, il n'y a pas de place pour stocker. –

+0

Perharps vous devriez demander une prime. – Alerty

Répondre

0

Les membres privés? Si c'est le cas, essayez d'ajouter protected: avant les membres de vos classes.

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


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

Une autre chose est apparue après être retourné dans votre exemple de code. Il semble que vous essayez d'utiliser le polymorphisme. Le seul problème est que vous dynamisez l'objet pointeur partagé vers un WidgetSet. Après avoir lu quelques documentation, je crois que vous devriez écrire resource.get_pointer() parce que vous voulez lancer le pointeur dans l'objet shared_ptr et pas l'objet shared_ptr lui-même. Je ne suis pas vraiment familier avec boost donc s'il vous plaît dites-moi si cela a un sens!

+0

Un autre détail que j'aurais dû montrer à l'origine: toutes ces pièces sont publiques. Boost fait un peu de magie en ajoutant dynamic_pointer_cast en tant que wrapper autour du dynamic_cast standard. Ce que vous décrivez semble être une erreur assez commune, et probablement la raison pour laquelle ils ont travaillé cette magie en premier lieu. Si vous faites un get(), dynamic_cast, puis l'assigner à un autre shared_ptr, il sera supprimé deux fois. – James

+0

Très vrai! Je lisais un peu trop vite. – Alerty

1

Sans voir toute votre classe AbstractGroup, il est difficile d'en être sûr, mais il semble que vous n'ayez aucune fonction virtuelle dans votre hiérarchie de classe. Essayez de définir un destructeur virtuel dans AbstractGroup (même en ligne) et voyez si cela fait la différence. Sans une seule fonction virtuelle, il n'y a pas de vtable et donc pas de place pour bloquer les données typeinfo.

+0

Désolé, j'aurais dû le montrer. Il y a certainement des membres virtuels de chaque classe. – James