我有一个模板类,我已经用它的指针(Decorator模式)进行了子类化。我添加了一个getBase()
调用,以返回指向任何其他子类的基类的指针。但是,当我使用getBase()
并调用基类类方法时,我得到一个链接器错误,它在干预(Decorator)类中找不到该方法的符号?
像这样:
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 );
}
请注意,fun( istream& )
中没有D<T>
的定义。目的是让客户端使用指向基址的指针来调用B<T>::fun( istream& )
当客户端构造Dagain
对象时,链接器说(基本上):
Client.o:
(.data.rel.ro. --stuff--
[vtable for D<T>]:
undefined reference to
'D<T>::fun( basic_istream<char, char_traits<char> >&)'
但是,我并没有打电话给 D 对fun(istream&)
的定义......它甚至都没有!我正在使用指针直接指向基类...当我为D<T>::fun(istream&)
添加一个定义工作时,但我不明白为什么?
答案 0 :(得分:1)
您忘记在模板定义中指定模板参数。此外,您还有一些错误。这是工作代码:
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 :(得分:0)
我不是C ++专家,也不确定这是否与模板有关,但如果我们忽略模板,我认为你的问题的一部分可能就是B中的fun()不是虚拟的。
当你调用getBase()时,你得到一个静态类型的B *,然后当你调用fun()时,你得到的是B版本而不是DAgain版本。我认为链接器会抱怨你没有为B定义版本(因此也没有为D定义)。在DAgain中覆盖fun()这一事实是不够的,因为绑定是静态的。
另一个选择是返回B *而不是B *可能是问题,但我最近还没有充分利用C ++。
答案 2 :(得分:0)
在我看来,getBase
正在返回错误的类型。它应该返回正确类型的基类:
template <typename T>
class D : public class B<T>
{
...
//Looks like B
B<T>* getBase() { return base_ ; }
private:
B<T>* base_;
};
答案 3 :(得分:0)
你所谓的“基础”实际上不是--D有一个真正的B基(由于继承)和一个假的通过该指针。至于为什么当你看起来根本没有虚拟机时,编译器抱怨vtable,这很奇怪 - 你确定你没有虚拟的地方吗?