C++ 协变返回类型
10.3/5美元 “重写的返回类型 功能应与 被重写对象的返回类型 类的函数或协变函数 如果函数是D::f 重写函数B::f,返回 函数的类型是协变的 如果他们满足以下条件 标准: -两者都指向 类或对类的引用98) -返回类型为B::f的类 与中的类是同一类 返回类型为D::f,或是 不含糊的、可访问的、直接或间接的 中类的间接基类 D::f的返回类型 -两个指针或引用都具有 相同的简历资格和 D::f的返回类型中的类类型 具有与或相同的简历资格 简历资历不如班级 输入B::f的返回类型。 我写了上面的实验代码,发现Comeau的错误/警告不符合要求。第9行中的警告似乎表明返回类型中的cv限定符没有意义。正是这个原因导致代码格式错误C++ 协变返回类型,c++,covariant,C++,Covariant,10.3/5美元 “重写的返回类型 功能应与 被重写对象的返回类型 类的函数或协变函数 如果函数是D::f 重写函数B::f,返回 函数的类型是协变的 如果他们满足以下条件 标准: -两者都指向 类或对类的引用98) -返回类型为B::f的类 与中的类是同一类 返回类型为D::f,或是 不含糊的、可访问的、直接或间接的 中类的间接基类 D::f的返回类型 -两个指针或引用都具有 相同的简历资格和 D::f的返回类型中的类类型 具有与或相同的简历资格 简历资历不如班级 输入B::f的返回类型。 我
"ComeauTest.c", line 5: warning: type qualifier on return type is meaningless
virtual const A * const f(){return 0;}
^
"ComeauTest.c", line 9: warning: type qualifier on return type is meaningless
virtual const B * volatile f(){return 0;}
^
"ComeauTest.c", line 9: error: return type is not identical to nor covariant with
return type "const A *const" of overridden virtual function function
"X::f"
virtual const B * volatile f(){return 0;}
^
所以问题是,Comeau在第9行给出“警告”消息是否正确?我知道这是一种实现定义的行为,Comeau只是想表现得好一点。但在这种情况下,这充其量是令人困惑的。第5行和第9行的警告是,“返回类型上的类型限定符”毫无意义“是因为非类类型的R值从不符合cv条件 由于按值返回的函数的结果是右值,指针是非类类型,因此返回的指针不是cv限定的,即使返回类型说它是 此警告与协方差无关。以下功能将导致相同的警告:
int* volatile f() { return 0; }
对于10.3/5中引用的文本:
两个指针或引用具有相同的cv限定
这是指返回类型的顶级限定(即const int*volatile
中的volatile
)。虽然顶级限定毫无意义,但它确实会影响函数的类型,因此鉴于上面的f
声明,此代码段是不正确的:
int* (*q)() = f; // error: can't convert int* volatile (*)() to int* (*)()
同样,如果派生类成员函数中返回类型的顶级cv限定与基类中返回类型的顶级cv限定不匹配,则派生类成员函数不会重写基类成员函数
D::f
返回类型中的类类型具有与B::f
返回类型中的类类型相同或更少的cv限定
这是指返回值的类类型的限定(即
const int*volatile
中的const
)。此规则意味着派生类成员函数中返回类型的限定必须等于或小于其重写的基类成员函数的返回类型。我在错误消息中看到了volatile
,但在示例源代码中没有看到。你给我们看的代码就是你正在编译的代码吗?@Thanatos:我刚刚在OP+1之后向你和James纠正了它,这是我见过的最晦涩的角落案例。我如何解释协方差条件第三项中的两个“粗体”部分,特别是和条件的第二部分?如果它“确实影响函数的类型”,我认为Comeau发出的警告消息在这种情况下可能是不正确的。或者不是吗?@chubsdad:f(它是int*volatile
)的返回类型与右值函数调用表达式f()
(它是int*
)的类型之间存在差异。Comeau警告您,对于后一种情况,顶级cv限定符是没有意义的。@chubsdad:对于实际代码,通常建议不要在顶级a非类返回类型中使用cv限定符。例如,它可能会导致问题。
int* (*q)() = f; // error: can't convert int* volatile (*)() to int* (*)()