g++ linker error--typeinfo, but not vtable
I know the standard answer for a linker error about missing typeinfo usually also involves vtable and some virtual function that I forgot to actually define.
I'm fairly certain that's not the situation this time.
Here's the error:
UI.o: In function 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 for Graphics::Widgets::WidgetSet'
Running c++filt on the obnoxious mangled name shows that it actually is looking at .boost::shared_ptr::shared_ptr(boost::shared_ptr const&, boost::detail::dynamic_cast_tag)
The inheritance hierarchy looks something like
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();
...
};
Then there's this:
class UI : public GroupByState
{
public:
virtual ~UI();
...
void LoadWidgets( GroupByState::Ptr resource );
...
};
Then the original implementation:
void UI::LoadWidgets( GroupByState::Ptr resource )
{
WidgetSet::Ptr tmp( boost::dynamic_pointer_cast< WidgetSet >(resource) );
if( tmp )
{
...
}
}
Stupid error on my part (trying to cast to a sibling class with a shared parent), even if the error is kind of cryptic.
Changing to this:
void UI::LoadWidgets( AbstractGroup::Ptr resource )
{
WidgetSet::Ptr tmp( boost::dynamic_pointer_cast< WidgetSet >(resource) );
if( tmp )
{
...
}
}
(which I'm fairly sure is what I actually meant to be doing) left me with a very similar error:
UI.o: In function 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 returned 1 exit status
dynamic_cast_tag is just an empty struct in boost/shared_ptr.hpp. It's just a guess that boost might have anything at all to do with the error.
Passing in a WidgetSet::Ptr totally eliminates the need for a cast, and it builds fine (which is why I think there's more going on than the standard answer for this question).
Obviously, I'm trimming away a lot of details that might be important. My next step is to cut it down to the smallest example that fails to build, but I figured I'd try the lazy way out and take a stab on here first.
TIA!
EDIT: Show some more details that people have commented about
Without seeing your whole AbstractGroup class it's hard to be sure, but it sounds like you may not have any virtual functions in your class hierarchy. Try defining a virtual destructor in AbstractGroup (even an inline one will do) and see if that makes the difference. Without a single virtual function, there's no vtable and thus no place to hang the typeinfo data.
Are the members private? If so try adding protected:
before the members of your classes.
class AbstractGroup
{
protected:
typedef boost::shared_ptr<AbstractGroup> Ptr;
...
};
class WidgetSet : public AbstractGroup
{
protected:
typedef boost::shared_ptr<WidgetSet> Ptr;
...
};
Another thing showed up after going back into your code sample. It looks like your trying to use polymorphism. The only problem is that you are dynamically casting the shared pointer object to a WidgetSet. After reading some documentation, I believe you should write resource.get_pointer()
because you want to cast the pointer in the shared_ptr object and not the shared_ptr object itself. I am not really familiar with boost so please tell me if this makes any sense!
精彩评论