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?

0


a source to share


4 answers


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

      

+1


a source


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.

0


a source


It seems to me that yours is getBase

returning the wrong type. It should return the correct base class type:

template <typename T>
class D : public class B<T>
{
  ...
  //Looks like B
  B<T>* getBase() { return base_ ; }
  private:
    B<T>* base_;
};

      

0


a source


What you call "base" is not really - D has a real base B (due to inheritance) and a fake one with that pointer. As for why the compiler whines about a vtable when you don't have any virtual machines at all, it's weird - are you sure you don't have a virtual one?

0


a source







All Articles