C++ 不推荐的虚拟机协变返回类型

C++ 不推荐的虚拟机协变返回类型,c++,inheritance,g++,virtual,covariance,C++,Inheritance,G++,Virtual,Covariance,大家好,我在用代码块编译代码时收到了一些警告,这些代码块不知道是什么意思,应该忽略它们,否则会在程序执行过程中反映出来 \src\..\inc\UTDB_Field.h|56|warning: deprecated covariant return type for 'virtual int* UTDB_intField::get_valField() const' \src\..\inc\UTDB_Field.h|19|warning: overriding 'virtual void* UT

大家好,我在用代码块编译代码时收到了一些警告,这些代码块不知道是什么意思,应该忽略它们,否则会在程序执行过程中反映出来

\src\..\inc\UTDB_Field.h|56|warning: deprecated covariant return type for 'virtual int* UTDB_intField::get_valField() const'
\src\..\inc\UTDB_Field.h|19|warning: overriding 'virtual void* UTDB_Field::get_valField() const'
事实上,
virtualvoid*UTDB\u Field::get\u valField()const
const是UTDB\u Field(基类)中的纯虚拟函数,
virtual int*UTDB\u intField::get\u valField()const
const是派生函数(UTDB\u intField)

我找到了几个关于co variant return type含义的解释,但我理解的是,返回类型void*(在我的例子中)丢失了,被int*替换了,对我来说,这就是我的目标,我想要一个泛型的返回类型,每个派生类将负责自己的返回

下面是在派生类UTDB_intField中定义的my运算符==:

 virtual bool operator==(const UTDB_Field& Field) const
{
     if(this->typeF==(Field.get_typeField()))
      {
           if(this->nameF==(Field.get_nameField()))
           {
                if (this->val== Field.get_valField())
                return true;
                else
                {
                    std::cout<<" val 1: "<<*(this->get_valField())<<" and val2:  "<<*(int*)Field.get_valField() <<" are different"<<std::endl;
                    return false;
                }
            }
            else
                {
                    std::cout<<" name 1: "<<this->get_nameField()<<" and name 2: "<<Field.get_nameField() <<" are different"<<std::endl;
                    return false;
                }
      }
      else  {
                std::cout<<" type "<<this->typeF<<" and "<<Field.get_typeField() <<" are two incomparable types"<<std::endl;
                return false;
            }
};
虚拟布尔运算符==(常量UTDB_字段和字段)常量
{
if(this->typeF==(Field.get_typeField()))
{
如果(this->nameF==(Field.get_nameField())
{
if(this->val==Field.get_valField())
返回true;
其他的
{

std::cout抛开设计考虑和意见不谈,这里唯一真正的问题是您不在标准范围内,它不会与其他编译器编译。原因是标准只允许返回类型因协方差而不同。换句话说,重载的返回类型必须与基方法的类型相同;或者隐式强制转换到基的驱动类型。这假定返回的是指针/ref

协变返回类型(通常)的目的是使类A可以有一个从某个例程返回“A*”的方法。类B派生自A并重载该方法,但确实希望返回“B*”。当然它可以说它返回“A*”,因为它是“B*”,但您需要额外的信息

这样,如果有人正在使用类型为B的对象,并且已知该对象为B,则可以利用该方法返回(至少)a B*的知识,而无需向上转换

你在这里所做的很尴尬,但逻辑上很好。如果你把对象用作UTDB_字段*这个方法会给你一个void*它可以是任何东西。如果你把它用作UTDB_IntField*,希望它真的是,那么你会从原型中得到额外的信息,返回的不仅仅是一个void,实际上是一个int


我将不讨论这是好是坏,但了解将其带到其他编译器的可移植性问题可能很重要。

您试图做的似乎没有意义。如果它们返回完全不同的指针类型,为什么它们是同一个函数?您如何使用它?而不是带有overr的虚拟函数在IDE中,对
UTDB\u intField
使用
get\u intvalField
。多态性不会使任何函数变为虚拟函数,并键入cast对象而不是返回值我需要使用一个泛型对象作为UTDB_字段,如果我想得到它的值,我不知道他是哪种类型,所以我这样做了,你说的“或者使所有函数都不虚拟,并将对象类型转换为返回值”是什么意思对不起,我不是在c++中做实验,但是你怎么能得到它的值?如果你不知道它是什么类型的,你怎么知道你得到了什么类型的指针?在我看来,你创建了一个无法使用的函数。正确的修复方法取决于你想如何使用它。我不明白你打算如何使用它,所以我很难解释我将告诉您如何修复它。您通常会如何处理基函数返回的
void*
?您是否仅从派生类调用基类的函数?如果是,它应该是不同的函数名,并且应该受到保护。我需要在派生类中使用此原型虚拟布尔运算符重载运算符====(const-UTDB\u-Field&Field)const(将这个类与从基派生的另一个类进行比较),所以我需要这样得到它的值:`UTDB\u-Field*UTField=new-UTDB\u-intField(“name”,val2);UTDB\u-Field*UTField2=new-UTDB\u-strField(“Currency”,val2);std::coutt感谢您的时间,这很清楚,但我的目标是不会回来的(get_valField)我想要的对象的ref只是返回一个指向我的字段值的指针(int*,string*,float*…),我测试了代码,它工作了,甚至我的运算符==给出了想要的结果。如果我比较intField和strField,我担心警告是非常严重的,我应该删除它,或者它没问题,因为我得到了我想要的。@oumaya:红色警报!永远不要这样做。说真的,这绝对不是。“我写了一些我不理解或违反规则的代码,但当我测试它时,它恰好符合我的要求。”例如,它可能会在下一版本的编译器或其他编译器上中断。这会给你带来麻烦。如果你解释了你实际试图获得的行为(请参阅我关于
运算符==
的工作原理或指针使用方法的评论)我们可以告诉你这样做的合法方式。谢谢@David Schwartz我真的很尴尬,我不知道该怎么办,我编辑了我的问题以使其更清楚,我真的很困惑我是否应该用一个使用模板的类UTDB_字段来替换所有这些(
模板
)对于我的字段类型,是否将我的
void*
替换为
MyType*
string  a="CurrField";
string* val=&a;
int b=5;
int* val2=&b;

std::cout<<"  *Construction*"<<endl;

UTDB_Field* UTField=new UTDB_strField("name",val);

UTDB_Field* UTField2=new UTDB_intField("Currency",val2);

std::cout<<" --------------- "<<std::endl;
std::cout<<"result of comparison "<<(*UTField2==(*UTField))<<endl;