【问题标题】:implementing an abstract base class function in another template base class在另一个模板基类中实现抽象基类函数
【发布时间】:2010-12-14 16:53:14
【问题描述】:

我有一个 Visual Studio 2008 C++ 项目,其中有一个继承自抽象基类的类和另一个在抽象基类中实现函数的模板类。例如:

class Foo;

struct Buzz
{
    virtual ~Buzz() {};
    virtual void Buzz_Do( Foo* ) = 0;
};

class Base
{
public:
    virtual ~Base() {};
    virtual void Base_Do( Buzz* ) = 0;
};

template< class T >
class Bar
{
public:
    virtual void Base_Do( Buzz* v )
    {
        v->Buzz_Do( static_cast< T* >( this ) );
    };
};

class Foo : public Base, public Bar< Foo >
{
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo c;
    return 0;
}

不幸的是,这会产生编译器错误:

1>MyApp.cpp(39) : error C2259: 'Foo' : cannot instantiate abstract class
1>        due to following members:
1>        'void Base::Base_Do(Buzz *)' : is abstract
1>        MyApp.cpp(17) : see declaration of 'Base::Base_Do'

我尝试将公共using Bar&lt; Foo &gt;::Base_Do; 添加到class Foo,但这没有帮助。

有没有办法完成这项工作,或者我需要在Foo 中放置一个具体的Base_Do() 实现而不使用Bar&lt;&gt;

谢谢, 保罗H

【问题讨论】:

  • 只是为了澄清术语:具有纯虚函数的类在 C++ 中称为 抽象类,而不是“虚拟基类”。
  • -1 不正确的断言,无效的代码。这不是您的实际代码,如果您的断言与现实有任何相似之处,那么呈现的代码不会。

标签: c++ templates compiler-errors


【解决方案1】:

如果可能,让Bar&lt;&gt; 从 Base 派生, 而 Foo 仅派生自 Bar&lt;T&gt;

【讨论】:

  • 请,请,请,请不要尝试虚拟继承。 Amok 的解决方案确实是你应该走的路。
【解决方案2】:

当这些基础不相关时,无法使在一个基础中定义的函数覆盖另一个基础中的同名函数。它不是那样工作的。您要么必须让您的模板库继承自抽象库,要么在派生类中编写函数以调用非抽象库中的函数。

你做什么很大程度上取决于你的问题。我通常更喜欢前者,但遇到了不可能的情况(因为我需要的碱基根本不相关)并使用后者。

【讨论】:

    【解决方案3】:

    就编译器所知,您的模板函数并没有实际上实现了基类中的函数。编译器认为Base::Base_DoBar&lt;T&gt;::Base_Do 是两个完全不相关的函数,而不是一个的实现。

    编译器看到的是Foo 最终包含两个(几乎)同名的函数:Base::Base_DoBar&lt;T&gt;::Base_Do。 Bar 根本没有实现Base 的接口。

    我认为您真正想要的是Bar&lt;T&gt; 继承自Base 并实现Base_Do。然后让Foo 仅从Bar&lt;Foo&gt; 继承。

    但即便如此,您能否更清楚地告诉我们您实际上要解决什么问题?然后我们可以就如何解决这个问题提供建议。 BuzzFooFooBarBase 之间的关系让我感到困惑。

    编辑: 另请参阅http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.10,因为这可能会提供一种仍然允许您使用 mixin 的替代机制。

    【讨论】:

      【解决方案4】:

      你试过了吗:

      template< class T , class K>
      
      class Bar: public K
      {
      public:
          virtual void Base_Do( Buzz* v )
          {
              v->Buzz_Do( static_cast< T* >( this ) );
          };
      };
      
      class Foo : public Bar< Foo, Base >
      {
      };
      

      Foo 派生自 Base,它具有未定义的虚方法。你可以像我写的那样做或推导virtual

      【讨论】:

        【解决方案5】:

        由于Foo扩展了Base,在实例化Foo(Foo c;)之前,需要实现Base的所有虚方法。在您的示例中,您需要实现virtual void Base_Do( Buzz* )

        【讨论】:

          【解决方案6】:

          查看错误:

          > 1>MyApp.cpp(39) : error C2259: 'Foo' :
          > cannot instantiate abstract class 1>  
          > due to following members: 1>       
          > 'void Base::Base_Do(Buzz *)' : is
          > abstract 1>        MyApp.cpp(17) : see
          > declaration of 'Base::Base_Do'
          

          Foo 是一个抽象类。您不能创建它的实例。首先实现它从基类继承的所有虚函数。

          【讨论】:

          • 对于您的最后一个问题,这是完全合法的,被称为“Curiously Recurring Template Pattern”,简称 CRTP。
          • @Alexandre。是的。我只是注意到了。 :-)
          【解决方案7】:

          我有一个 Visual Studio 2008 C++ 我有一门课的项目 从虚拟基类继承,并且 另一个实现的模板类 虚拟基类中的一个函数。

          • 错误:您的代码没有虚拟基类。

          这是你的代码(我正在写这篇文章):

          class Foo;
          
          struct Buzz
          {
              virtual ~Buzz() {};
              virtual void Buzz_Do( Foo* ) = 0;
          };
          
          class Base
          {
          public:
              virtual ~Base() {};
              virtual void Base_Do( Buzz* ) = 0;
          };
          
          template< class T >
          class Bar
          {
          public:
              virtual void Base_Do( Buzz* v )
              {
                  v->Buzz_Do( static_cast< T* >( this ) );
              };
          };
          
          class Foo : public Base, public Bar< Foo >
          {
          };
          
          int _tmain(int argc, _TCHAR* argv[])
          {
              Foo c;
              return 0;
          }
          

          进一步,

          • 错误:纯虚成员函数Buzz_Do没有在任何地方实现。

          • 错误:您的代码缺少main 函数(我猜读者可以提供一个)。

          • 错误:宏(或类型)_TCHAR 未定义。

          话虽如此,虚拟继承(您声称您的实际代码正在使用)是您似乎打算提出的问题的一种可能答案。

          但是,由于您提供的代码无效并且对该代码的断言不正确,因此不能说太多。我注意到其他人已经尝试过了。也许,如果幸运的话,其中一个答案会符合要求,但这只是机会游戏。

          干杯,

          【讨论】:

          • @downvoter:请说明你投反对票的原因,以便其他人看到它为什么愚蠢。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-06-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-14
          • 2021-06-25
          • 2015-02-25
          相关资源
          最近更新 更多