By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,040 Members | 1,815 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,040 IT Pros & Developers. It's quick & easy.

Likely causes of Unresolved external symbol in pure virtual function

P: n/a

Hi All

I have a pure virtual function in my base class that my derived
instances override. What are the likely causes for VC++ 7.1 to
complain of unresolved external symbol on that pure virtual function?
I tried to rule out the obvious mistakes. The virtual fn. is
definitely defined in the derived classes. Here is what I have:

// file a.h
class base
{
public:
virtual long somefunc() = 0;
};

template<typename T>
class derv : public base
{
virtual long somefunc();
};

// file a.cpp
template<typename T>
long derv<T>::somefunc()
{
}

I can't understand why I am getting the linker error -- what is my
mistake?
Earlier I had all these code in a single .cpp file (for testing
purposes), then I started re-organizing my project separating code into
headers and newer source files and all of a sudden the pure virtual
functions are giving me linker errors.

I have also ensured that the .cpp files of my derived classes that
define the pure virtual function generate proper .obj files.

What am i missing?

Apr 24 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Dilip wrote:
// file a.cpp
template<typename T>
long derv<T>::somefunc()
{
}

I can't understand why I am getting the linker error -- what is my
mistake?


Each translation unit must (generally) see complete template definitions to
expand them.

Move the body of somefunc() from a.cpp to a new file, call it a.inl, and
then #include this into every translation unit that instantiates your
template derv<> with a new type.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 24 '06 #2

P: n/a
Dilip wrote:
I have a pure virtual function in my base class that my derived
instances override. What are the likely causes for VC++ 7.1 to
complain of unresolved external symbol on that pure virtual function?
I tried to rule out the obvious mistakes. The virtual fn. is
definitely defined in the derived classes. Here is what I have:

// file a.h
class base
{
public:
virtual long somefunc() = 0;
};

template<typename T>
class derv : public base
{
virtual long somefunc();
};

// file a.cpp
template<typename T>
long derv<T>::somefunc()
{
}

I can't understand why I am getting the linker error -- what is my
mistake?
Isn't this in the FAQ? See section on templates.
[..]


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 24 '06 #3

P: n/a
Phlip wrote:
Dilip wrote:
// file a.cpp
template<typename T>
long derv<T>::somefunc()
{
}

I can't understand why I am getting the linker error -- what is my
mistake?
Each translation unit must (generally) see complete template definitions to
expand them.


That should teach me a lesson -- mucking around with templates without
understanding everything about them.
Move the body of somefunc() from a.cpp to a new file, call it a.inl, and
then #include this into every translation unit that instantiates your
template derv<> with a new type.


would this be appropriate:
================================
// file derv1.inl
template<typename T>
long derv<T>::somefunc()
{
}
================================
================================
// file a.h
class base
{
virtual void somefunc() = 0;
};

template<typename T>
class derv1 : public base
{
virtual void somefunc();
};

// include this at the very bottom of a.h
// likewise include the defn of all classes that might derive from base
#include ".\derv1.inl"
================================
================================
// file a.cpp
#include ".\a.h"
================================

will this work?

Apr 24 '06 #4

P: n/a
Victor Bazarov wrote:
Dilip wrote:
I can't understand why I am getting the linker error -- what is my
mistake?


Isn't this in the FAQ? See section on templates.


Victor
Thanks for the pointer. I looked up the FAQ and read this (and others
too):
http://www.parashift.com/c++-faq-lit...html#faq-35.15

While I understood the motivation, Philp's idea seems to be easier
because I am getting confused with 2 issues here.

#1) Cline's faq basically asks you to do a empty instantiation in the
..cpp file. So if my main code creates several different instances of
the derived template class with different template parameters, should I
include a empty instantiation for every such parameter?

#2) I had a situation like this that I couldn't immediately figure out
what to do:

// file a.h
class base
{
virtual void dosomething() = 0;

// I need the type parameter passed to derv for _only_
// this method in base
template<typename T>
void somefunc();
};

template<typename T>
class derv1 : public base
{
virtual void dosomething();
};

// derv1.cpp
template<typename T>
void derv<T>::dosomething()
{
somefunc<T>();
}

// file main.cpp
base* pBase = new derv1<int>();
pBase->dosomething();

how should I now define the empty instantiation for somefunc()?

is it:

template class base::somefunc<???>;

2 observations:

1. The above does not even compile (obviously the real code doesnt have
???)
2. the type parameter is dependant on the derived classes -- each of
them pass in their own stuff. How do I forward declare it?

Apr 24 '06 #5

P: n/a
Dilip wrote:
Each translation unit must (generally) see complete template definitions
to expand them.
That should teach me a lesson -- mucking around with templates without
understanding everything about them.


Note I said "generally". That's because I, too, muck around with templates
without understanding everything about them.

Modern compilers are supposed to overcome this limitation, but I don't know
how the new system works, or how many compilers support it. So almost all
projects use their templates the way we are now discussing...
would this be appropriate:
================================
// file derv1.inl
template<typename T>
long derv<T>::somefunc()
{
}
================================
================================
// file a.h
class base
{
virtual void somefunc() = 0;
};

template<typename T>
class derv1 : public base
{
virtual void somefunc();
};

// include this at the very bottom of a.h
// likewise include the defn of all classes that might derive from base
#include ".\derv1.inl"
================================


No, because that defeats the purpose of an INL file. Users of a.h might want
to know about the template's declaration without needing to know its
definition. Your system might as well put the template function body inside
a.h. There's nothing special about the .inl extension.

Only include a.inl in every .cpp file that needs it, and this should be
fewer files than need a.h. Generally.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 24 '06 #6

P: n/a
Dilip wrote:
Victor Bazarov wrote:
Dilip wrote:
I can't understand why I am getting the linker error -- what is my
mistake?
Isn't this in the FAQ? See section on templates.


Victor
Thanks for the pointer. I looked up the FAQ and read this (and others
too):
http://www.parashift.com/c++-faq-lit...html#faq-35.15

While I understood the motivation, Philp's idea seems to be easier
because I am getting confused with 2 issues here.

#1) Cline's faq basically asks you to do a empty instantiation in the
.cpp file. So if my main code creates several different instances of
the derived template class with different template parameters, should
I include a empty instantiation for every such parameter?


There is no such thing as "empty instantiation". You probably mean
an explicit instantiation. It can help, but it's not the best solution.
An explicit instantiation causes the compiler to generate code for some
combination of the template arguments. If some user of your template
wants to have a different combination of template arguments than any of
those that you predicted, the user's compiler won't be able to generate
the instantiation if it does not see the code for the template itself.
#2) I had a situation like this that I couldn't immediately figure out
what to do:

// file a.h
class base
{
virtual void dosomething() = 0;

// I need the type parameter passed to derv for _only_
// this method in base
template<typename T>
void somefunc();
};

template<typename T>
class derv1 : public base
{
virtual void dosomething();
};

// derv1.cpp
template<typename T>
void derv<T>::dosomething()
{
somefunc<T>();
}

// file main.cpp
base* pBase = new derv1<int>();
pBase->dosomething();

how should I now define the empty instantiation for somefunc()?

is it:

template class base::somefunc<???>;
I think you'd need to put

template void derv<int>::dosomething();

in the 'derv1.cpp'.
2 observations:

1. The above does not even compile (obviously the real code doesnt
have ???)
2. the type parameter is dependant on the derived classes -- each of
them pass in their own stuff. How do I forward declare it?


Forward declare what? You don't need to do anything special, since
you have the template definition (which contains the declaration of
'dosomething').

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 24 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.