gpt4 book ai didi

c++ - 覆盖虚函数协变返回类型(两个指针)

转载 作者:太空宇宙 更新时间:2023-11-04 15:41:42 26 4
gpt4 key购买 nike

我正在尝试覆盖基类函数。派生类型和基类型都返回指针,因此根据我在 google 和 stackoverflow 上阅读的一些帖子,它应该是协变的。

但是在 MSVC2013 中有以下类:

class PSBaseObject
{
public:
PSBaseObject() {}
virtual ~PSBaseObject() {}

virtual void* data() { return this; }
virtual const void* data() const { return this; }
};

template<typename T>
class PSObject : public PSBaseObject
{
private:
T* data_;

public:
PSObject(T* object) : data_(object) {}
~PSObject() { delete data_; }

T* data() { return data_; }
const T* data() const { return data_; }
};

我得到一个错误:

'PSObject<data>::data': overriding virtual function return type differs and is not covariant from 'PSBaseObject::data'

数据定义和使用如下:

typedef struct
{
void* hFileMap;
void* pData;
std::size_t size;
} data;

data* info = new data();

auto ptr = new PSObject<data>(info);

为什么不是协变的?

知道我在 MSVC2013 中做错了什么吗?代码在 g++ 4.8.1 中编译并运行良好。

最佳答案

MSVC 是对的; void*T* 不协变。引用标准(10.3 [class.virtual],第 7 节):

The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

— both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes

— the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f

— both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

void 不是 T 的基类(= data),所以返回类型不是协变。


那么为什么要这条规则呢?嗯,这个想法是,如果你有

struct B {
virtual U* f();
};

struct D : B {
virtual V* f();
};

B* b1 = new B();
B* b2 = new D();
U* u1 = b1->f();
U* u2 = b2->f();

b1->f() 将调用 B::f,它返回 U*。但是 b2->f() 将调用 D::f,它返回 V*V 必须从 U 派生,以便从 D::f 返回的 V* 始终可以转换为U*.

现在,在这种情况下允许 Uvoid合理的,因为任何指向对象类型的指针都可以转换为 void*,即使 void 不是任何对象的基类。但标准并不要求允许。

该标准还说(1.4 [intro.compliance],第 8 段),

A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

所以 g++ 没有错。允许 Uvoid 是一个扩展,它不会改变任何格式良好的程序的行为,而 g++ em> 当您尝试编译此代码时发出警告。

关于c++ - 覆盖虚函数协变返回类型(两个指针),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21963734/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com