【问题标题】:Can't call base class method even though I have a pointer to it (Decorator)?即使我有一个指向它的指针(装饰器)也不能调用基类方法?
【发布时间】:2009-05-14 21:03:02
【问题描述】:

我有一个模板类,我用一个指向它的指针对其进行了子类化(装饰器模式)。我添加了一个getBase() 调用来返回指向基类的指针以用于任何进一步的子类。但是,当我使用 getBase() 并仅调用基类方法时,我收到一个链接器错误,它无法在中间(装饰器)类中找到该方法的符号?

像这样:

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

请注意,D&lt;T&gt; 中没有 fun( istream&amp; ) 的定义。目的是让客户端使用指向基址的指针来调用B&lt;T&gt;::fun( istream&amp; )

当客户端构造一个Dagain 对象时,链接器说(基本上):

Client.o:
(.data.rel.ro. --stuff--
[vtable for D<T>]:
undefined reference to
'D<T>::fun( basic_istream<char, char_traits<char> >&)'

但是,我没有调用 Dfun(istream&amp;) 的定义……它甚至没有!我直接使用指向基类的指针...当我为D&lt;T&gt;::fun(istream&amp;) 添加定义时,一切正常,但我不明白为什么?

【问题讨论】:

  • 这段代码包含太多不相关的东西和太多的编译错误(可能是由于将其修剪为这个问题的结果),需要认真考虑。如果您想要一个真正的答案,我建议使用可以真正编译并最小化显示问题的代码来编辑问题。
  • 我很抱歉。我必须从记忆中输入所有这些,因为我在工作中没有互联网连接。在我将问题减少到它的本质并且我可以编译它之后,我会再次尝试它。那我再发吧。

标签: c++ templates decorator


【解决方案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 );
}

【讨论】:

    【解决方案2】:

    我不是 C++ 专家,不确定这是否与模板有关,但如果我们忽略模板,我认为您的部分问题可能是 B 中的 fun() 不是虚拟的。

    当您调用 getBase() 时,您会得到 B* 的静态类型,然后当您在其上调用 fun() 时,您会从 B 中获取版本,而不是 DAgain 中的版本。我认为链接器会抱怨您没有为 B 定义版本(因此也为 D 定义)。由于绑定是静态的,因此在 DAgain 中覆盖 fun() 的事实是不够的。

    另一种选择是返回 B* 而不是 B* 可能是问题所在,但我最近使用 C++ 的次数还不够多。

    【讨论】:

      【解决方案3】:

      在我看来,您的 getBase 返回了错误的类型。它应该返回正确的基类类型:

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

      【讨论】:

        【解决方案4】:

        你所谓的“基础”实际上并不是——D 有一个真正的 B 基础(由于继承)和一个通过该指针的假基础。至于为什么编译器在你似乎根本没有虚拟变量时抱怨 vtable,这很奇怪——你确定你在某个地方没有虚拟变量?

        【讨论】:

        • 我认为他正在尝试做类似 javas' Thread Runnable 之类的事情。存储实际调用的 runnable 的 run 方法。 “这个”或“另一个可运行的”
        猜你喜欢
        • 2017-10-08
        • 2020-09-02
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 2016-11-23
        • 1970-01-01
        • 1970-01-01
        • 2019-01-08
        相关资源
        最近更新 更多