Can't call base class method even though I have a pointer to it (Decorator)?
I have a template class that I subclassed with a pointer to it (Decorator template). I added a call getBase()
to return a pointer to the base class for any subsequent subclasses. However, when I use this one getBase()
and only call the base class method, I get the linker error that it cannot find the symbol for this method in the intermediate class (Decorator)?
Like this:
template <typename T> class B {
public:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
auto_ptr<T> fun( istream& );
private:
MYFUN *fptr;
};
template <typename T>
class D : public class B<T>
{
D( typename B<T>::MYFUN *fPtr, B<T> *providedBase );
//Looks like B
B* getBase() { return base_ ; }
private:
B* base_;
};
template <typename T>
class Dagain : public class D<T>
{
//Looks like D
auto_ptr<T> fun( istream& );
};
auto_ptr<T>
Dagain::fun( istream& is )
{
this->getBase()->fun( is );
}
Note that there is no definition for fun( istream& )
in D<T>
. The goal is for the client to use a pointer to the base to callB<T>::fun( istream& )
When the client creates an object Dagain
, the linker says (basically):
Client.o:
(.data.rel.ro. --stuff--
[vtable for D<T>]:
undefined reference to
'D<T>::fun( basic_istream<char, char_traits<char> >&)'
But I don't name the D definition fun(istream&)
... it doesn't even have one! I am using the pointer directly to the base class ... When I add the definition for D<T>::fun(istream&)
, everything works, but I don't understand why?
a source to share
You forgot to specify a template parameter in your template definition. Also, you had a few more errors. Here's the working code:
template <typename T> class B {
public:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
auto_ptr<T> fun( istream& );
private:
MYFUN *fptr;
};
template <typename T>
class D : public B<T>
{
D( typename B<T>::MYFUN *fPtr, B<T> *providedBase );
//Looks like B
B<T>* getBase() { return base_ ; }
private:
B<T>* base_;
};
template <typename T>
class Dagain : public D<T>
{
//Looks like D
auto_ptr<T> fun( istream& );
};
template <typename T>
auto_ptr<T>
Dagain<T>::fun( istream& is )
{
this->getBase()->fun( is );
}
a source to share
I'm not a C ++ expert and I'm not sure if this has anything to do with templates, but if we ignore templates, I think part of your problem might be that fun () in B is not virtual.
When you call getBase () you get the static type B * and then when you call fun () you get the version from B, not the version in DAgain. I think the linker will complain that you haven't defined a version for B (and therefore for D). The fact that fun () is overridden in DAgain will not be sufficient since the binding is static.
Another option is that returning B * and not B * might be a problem, but I haven't played with C ++ recently enough.
a source to share