无效的协变返回类型
Invalid covariant return type
这是一些代表性代码,它得到了我遇到的错误:
class Data
{
};
class Table
{
virtual std::vector<Data*> getData() = 0;
virtual void putData(Data* dataItem) = 0;
virtual Data* getData(int index) = 0;
};
class DerivedData : Data
{
};
class DerivedTable : Table
{
std::vector<DerivedData*> getData() { return myData; } // invalid covariant return type
void putData(DerivedData *dataItem) { myData.push_back(dataItem); }
virtual DerivedData* getData(int index) { return myData[index]; } // invalid covariant return type
std::vector<DerivedData*> myData;
};
首先,我不太明白为什么 putData 的覆盖对参数的更改感到满意,但我无法更改 getData 的返回类型,尽管我很欣赏这是我可以从更多阅读中获得理解的东西。
其次,也是我的主要问题,如何更改此代码以使其工作。我的基本目标是允许多个类似"表"的对象来存储和控制数据对象。虽然每个数据对象将共享一些共同点,但表将控制和处理一些明显的差异。例如,一个表可能具有具有 name 参数的数据对象,因此该表将提供一个函数,该函数打印它所持有的所有数据名称的列表。这样,我就可以拥有适用于所有这些表对象的通用代码,以及仅适用于一种类型的表的专用代码。
很多事情都是错误的:
-
putData
的两个版本只是不同的、不相关的重载。在C++中没有覆盖虚函数的"逆变参数类型"这样的东西(即使有,它也会反过来!!将关键字override
添加到派生函数,以使编译器生成错误。 -
类模板的工作方式与您想象的方式不同。如果
template <typename T> class Foo
是一个类模板,那么Foo<X>
和Foo<Y>
是完全不同的、不相关的类,无论X
和Y
是否以任何方式相关。
正如@Beta所说,您可能只有一个简单的std::vector<std::unique_ptr<Data>>
作为主要数据结构。但无论如何,如果你真的必须有一些层次结构,这里有一个可能的"解决方案":
#include <memory>
#include <vector>
struct Data { virtual ~Data() { } };
struct Table
{
virtual ~Table() { }
typedef std::unique_ptr<Data> data_ptr;
typedef std::vector<data_ptr> dataset_type;
virtual dataset_type & getData() = 0;
virtual void putData(data_ptr dp) = 0;
virtual Data & getData(std::size_t n) = 0;
};
class DerivedTable : public Table
{
dataset_type myData;
public:
virtual void putData(data_ptr p) override
{
myData.push_back(std::move(p));
}
Data & getData(std::size_t n) override
{
return *myData[n];
}
// ...
};
无效的协变返回类型"实际上是由于您尝试更改getData()
的返回类型而导致的。虽然返回类型不是函数标识符的一部分,但它仍然受到一些限制。 重写某些基类的任何方法都应具有类似的行为。即虚拟方法实现将尝试对Data
进行上播,以返回从Table*
(而不是DerviedTable*
)的角度调用getData()
的客户端的有效指针。这可以与DerviedTable::getData(int)
上下文中的(Data*)myData[index]
进行比较。
这正是编译器
混淆的地方。class DerivedData : Data
{
};
该声明说DervidedData
私下继承Data
。 即DerviedData
的任何客户都"不知道"它实际上是一个Data
。 这也使得无法生成DerviedData* getData() override
代码,因为无法从DeviedTable::getData(int)
访问向上转换为Data
。
要使该错误消失,您可以使继承可见于公众:
class DerivedData : public Data
{
};
或交朋友
class DerivedData : Data
{
friend class DerivedTable;
};
虽然这个设计仍然是一个问题的主题。
- 如何获取std::result_of函数的返回类型
- 奇怪的结构&GCC&clang(void*返回类型)
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 自动返回类型匹配无效
- 具有引用返回类型的重写方法上的协变返回类型无效
- 对"无效的抽象返回类型"进行故障排除
- 无效的协变返回类型,嵌套类C
- 错误:返回类型 'class Polar' 不完整,无效使用类型 'polar'
- 返回并强制转换数组指针(错误:数组下标的类型..无效)
- 无效的协变返回类型
- 协变返回类型无效的转换错误
- 无效的协变返回类型错误
- 为"虚拟无效"指定的冲突返回类型
- 函数常量返回类型:类型引用的初始化无效
- 具有基类的CRTP试图获取派生类成员的返回类型:不完整类型的使用无效
- 嵌套迭代器和接口中的"无效协变返回类型"错误
- 嵌套类中的"无效协变返回类型"错误,该方法返回基于模板的对象
- 抽象类:成员函数virtual..的抽象返回类型无效
- 使用虚函数协变返回类型的c++无效转换错误