3

这是一些得到我遇到的错误的代表性代码:

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 的返回类型,尽管我很欣赏这是我可以从更多了解的东西阅读。

其次,也是我的主要问题,如何更改此代码以使其正常工作。我的基本目标是允许多个“表”之类的对象来存储和控制数据对象。虽然每个数据对象都有一些共同点,但表格将控制和使用一些明显的差异。例如,一个表可能具有带有名称参数的数据对象,因此该表将提供一个函数,该函数打印出它所拥有的所有数据名称的列表。通过这种方式,我可以拥有适用于所有这些表对象的通用代码,以及只适用于一种类型的表的专用代码。

4

2 回答 2

5

很多事情都是错的:

  1. 的两个版本putData只是不同的、不相关的重载。在 C++ 中,没有用于覆盖虚函数的“逆变参数类型”(即使有,它也会反过来!!)。将关键字添加override到派生函数以使您的编译器产生错误。

  2. 类模板不像你想象的那样工作。如果template <typename T> class Foo是类模板,那么Foo<X>Foo<Y>完全不同的、不相关的类,无论XY是否以任何方式相关。


正如@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];
    }

    // ...
};
于 2012-11-05T13:15:21.650 回答
1

“无效的协变返回类型”实际上是由于您尝试更改getData(). 尽管返回类型不是函数标识符的一部分,但它仍然受到一些限制。任何覆盖某些基类的方法都应该表现相似。即虚拟方法实现将尝试向上转换以返回从(not )角度Data调用的客户端的有效指针。这可以与from context of进行比较。getData()Table*DerviedTable*(Data*)myData[index]DerviedTable::getData(int)

这正是编译器感到困惑的地方。

class DerivedData : Data
{
};

这个声明说私有DervidedData继承。即任何客户都不“知道”它实际上是一个. 这也使得无法生成代码,因为无法从.Data DerviedDataDataDerviedData* getData() overrideDataDeviedTable::getData(int)

要消除该错误,您可以将继承公开:

class DerivedData : public Data
{
};

或者交个朋友

class DerivedData : Data
{
    friend class DerivedTable;
};

虽然这个设计仍然是一个问题。

于 2016-05-12T20:09:29.953 回答