1

我在一个基类中定义了一个纯虚函数 virtual int GetData() const = 0

在每个派生类中,我定义了一个枚举并尝试覆盖 GetData 函数返回(派生类特定枚举)值;

例如:

class Derived1 : public Base
{
public :
enum D1
{
   d1_1 = 0,
   d1_2 = 60,
   ...
   d1_100
};
D1 GetData () const;
};
class Derived2 : public Base
{
public :
enum D2
{
   d2_1 = 10,
   d2_2 = 39,
   ...
   d2_300
};
D2 GetData () const;
};

说我不能为所有类的所有枚举值定义相同的范围是非常重要的。上面的代码会产生编译错误:

error C2555: : overriding virtual function return type differs and is not covariant

任何建议 - 如何解决?

4

4 回答 4

2

在您的特定情况下,事实是您的virtual方法返回一个原始类型,它没有协变,因为它不能像System.ObjectC# 中那样放入常见类型。
您需要定义一个类作为所有返回类型的基类,以实现协方差。

来自维基百科:

Within the type system of a programming language, covariance and contravariance refers to the
ordering of types from narrower to wider and their interchangeability or equivalence in certain 
situations (such as parameters, generics, and return types).

covariant: converting from a specialized type (Cats) to a more general type (Animals): 
Every cat is an animal.

是文章的链接。

于 2013-04-07T19:04:26.743 回答
1

仅当您将基类的指针/引用替换为派生类的指针/引用时,才允许更改虚函数的返回类型,因为一个可以安全地转换为另一个。虽然枚举类型和int兼容,但它们在技术上并不相关。只需int在任何地方使用,因为枚举名称只是一种装饰,根本不会影响任何东西。

于 2013-04-07T19:06:40.570 回答
1

您的设计需要修复,但仅关于您可以做的技术

class Derived1
    : public Base
{
public:
    enum D1
    {
       d1_1 = 0,
       d1_2 = 60,
       ...
       d1_100
    };
    D1 GetD1Data () const;
    int GetData() const override { return GetD1Data(); }
};
于 2013-04-07T19:06:50.853 回答
1

根据 C++11 ISO 10.3/7:

覆盖函数的返回类型应与被覆盖函数的返回类型相同或与函数的类协变。如果函数 D::f 覆盖函数 B::f,则函数的返回类型如果满足以下条件,则它们是协变的

都是类的指针,都是类的左值引用,或者都是类的右值引用

— B::f 的返回类型中的类与 D::f 的返回类型中的类是同一类,或者是 D 的返回类型中的类的明确且可访问的直接或间接基类: :F

— 指针或引用都具有相同的 cv 限定,并且 D::f 的返回类型中的类类型具有与 B::f 的返回类型中的类类型相同或更少的 cv 限定。

协方差仅允许用于指针、左值/右值引用。我猜你不想通过引用或指针返回枚举。

但是,如果您接受静态线程本地缓冲区,则可以使用以下方法:

现场演示

class EnumA
{
    int value_;
public:
    explicit EnumA(int v)
        : value_{v}
    {}
    int value() const
    {
        return value_;
    }
};
struct EnumB: EnumA
{
    enum EnumB_T{one,two};
    explicit EnumB(EnumB_T v)
        : EnumA{v}
    {}
    EnumB_T value() const
    {
        return EnumB_T(EnumA::value());
    }
};

struct A
{
    virtual const EnumA &func() const
    {
        static thread_local EnumA result{0};
        return result = EnumA{1};
    }
};

struct B: A
{
    virtual const EnumB &func() const override
    {
        static thread_local EnumB result{EnumB::one};
        return result = EnumB{EnumB::two};
    }
};
于 2013-04-07T19:09:55.127 回答