首页 > 解决方案 > 在模板派生类中用协变返回类型覆盖虚函数

问题描述

我想覆盖模板派生类中的虚函数。但是,我想使用派生类作为返回类型。下面是对应的代码:

class Abstract {
  public:
    virtual Abstract* allocate() const = 0;
};
template <typename Derived>
class Base : public Abstract {
  public:
    Derived* allocate() const override {
      return new Derived;
    }
};
class Concrete : public Base<Concrete> {
  public:
};
int main() {
  Concrete c;
  delete c.allocate();
}

不幸的是,我的编译器无法识别它Derived实际上是从Abstract以下错误消息派生的并且失败。

mwe.cpp: In instantiation of ‘class Base<Concrete>’:
mwe.cpp:12:25:   required from here
mwe.cpp:8:14: error: invalid covariant return type for ‘Derived* Base<Derived>::allocate() const [with Derived = Concrete]’
     Derived* allocate() const override {
              ^~~~~~~~
mwe.cpp:3:23: note: overridden function is ‘virtual Abstract* Abstract::allocate() const’
 virtual Abstract* allocate() const = 0;
                       ^~~~~~~~

allocate函数移到Concrete类中可以解决问题,但在创建多个具体类时会导致代码重复。有没有办法让编译器知道它Derived实际上是从 派生的Abstract

标签: c++inheritancetypes

解决方案


您可以模拟协变返回类型:

这里的重点是类Reintroduce。没有它allocate会覆盖虚函数。有了它,它隐藏了继承的功能。

#include <iostream>

class Abstract {
  public:
    virtual Abstract* allocate() const = 0;
};

namespace details{
    class Reintroduce {};

    template <typename Derived>
    class AllocImpl : public Abstract
    {
    public:
        Abstract* allocate() const override {
            return new Derived;
        }
    };
}


template <typename Derived>
class Base : public details::AllocImpl<Derived> 
{
  public:
    Derived* allocate(details::Reintroduce = {}) const 
    {
      return static_cast<Derived*>(details::AllocImpl<Derived>::allocate());
    }
};

class Concrete : public Base<Concrete> {
  public:
};


int main() {
  Concrete c;
  delete c.allocate();
}

如果我们可以在没有的情况下实现它,那就太好了,AllocImpl但这会使调用变得模棱两可。


推荐阅读