c++ - 在模板派生类中用协变返回类型覆盖虚函数
问题描述
我想覆盖模板派生类中的虚函数。但是,我想使用派生类作为返回类型。下面是对应的代码:
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
?
解决方案
您可以模拟协变返回类型:
这里的重点是类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
但这会使调用变得模棱两可。
推荐阅读
- jekyll - Jekyll 中围栏代码块的水平滚动条
- arrays - 名称更改的 SKSpriteNode 数组?
- c++ - 在函数内部创建的对象的范围 - 如果在函数外部存储和访问引用,它们是否有效?
- api - Acumatica - 使用 API 创建考勤卡
- python - 如何找到一组 RGB 图像的最常见像素值,不包括黑色像素?
- python - 如何使用seaborn专门绘制集群的质心?
- android - 如何在 LiveData类中使用“I”作为具体类型参数?
- r - nsga2 约束 - R 中的 mco 包
- c++ - 在 Windows 10 上使用 Visual Studio 2019 构建的 Tesseract API c++ 程序在 Windows Server 2012 上崩溃
- ruby - 在 Ruby 中将表情符号转换为 HTML UTF-8