> C++中的共变返回类型意味着重写返回类型必须是引用或指针。< /P>,c++,inheritance,overriding,virtual,C++,Inheritance,Overriding,Virtual" /> > C++中的共变返回类型意味着重写返回类型必须是引用或指针。< /P>,c++,inheritance,overriding,virtual,C++,Inheritance,Overriding,Virtual" />

当覆盖虚拟方法时,Cat与动物不协变 P>当我在C++中学习方法重写规则时,我一直在阅读关于协变类型的文章,这些基本上看起来是一个子类或派生类(至少关于C++)的一个花哨词。我做了一些测试,发现有一个我不理解的异常。以下显示: struct Animal {}; struct Cat : Animal{}; Cat gCat; Animal* getAnimalPointer() { return &gCat; } // Returning covariant type by pointer, OK Animal& getAnimalReference() { return gCat; } // Returning covariant type reference, OK Animal getAnimalCopy() { return gCat; } // Returning covariant type by copy, OK // All good // Now testing virtual method overriding by using C++ feature of // allowing overriding virtual methods using covariant return types struct AnimalShelter { virtual Animal* getAnimalPointer() {}; virtual Animal& getAnimalReference() {}; virtual Animal getAnimalCopy() {} }; struct CatShelter : AnimalShelter { Cat* getAnimalPointer() override; // Returning covariant type by pointer, OK Cat& getAnimalReference() override; // Returning covariant type by reference, OK Cat getAnimalCopy() override; // Returning covariant type by copy, fail /* Visual Studio error: return type is not identical to nor covariant with return type "Animal" of overriden virtual function CatShelter::getAnimalCopy*/ }; 编辑:只有在虚拟情况下,C++才阻止你通过复制返回协变类型,看看火灾Langor的优秀答案可能的原因。还有一个与此类似的问题,在评论中有一个有趣的讨论,其原因是否是调用方不知道在虚拟调用的情况下为返回类型分配多少空间 < > > C++中的共变返回类型意味着重写返回类型必须是引用或指针。< /P>

当覆盖虚拟方法时,Cat与动物不协变 P>当我在C++中学习方法重写规则时,我一直在阅读关于协变类型的文章,这些基本上看起来是一个子类或派生类(至少关于C++)的一个花哨词。我做了一些测试,发现有一个我不理解的异常。以下显示: struct Animal {}; struct Cat : Animal{}; Cat gCat; Animal* getAnimalPointer() { return &gCat; } // Returning covariant type by pointer, OK Animal& getAnimalReference() { return gCat; } // Returning covariant type reference, OK Animal getAnimalCopy() { return gCat; } // Returning covariant type by copy, OK // All good // Now testing virtual method overriding by using C++ feature of // allowing overriding virtual methods using covariant return types struct AnimalShelter { virtual Animal* getAnimalPointer() {}; virtual Animal& getAnimalReference() {}; virtual Animal getAnimalCopy() {} }; struct CatShelter : AnimalShelter { Cat* getAnimalPointer() override; // Returning covariant type by pointer, OK Cat& getAnimalReference() override; // Returning covariant type by reference, OK Cat getAnimalCopy() override; // Returning covariant type by copy, fail /* Visual Studio error: return type is not identical to nor covariant with return type "Animal" of overriden virtual function CatShelter::getAnimalCopy*/ }; 编辑:只有在虚拟情况下,C++才阻止你通过复制返回协变类型,看看火灾Langor的优秀答案可能的原因。还有一个与此类似的问题,在评论中有一个有趣的讨论,其原因是否是调用方不知道在虚拟调用的情况下为返回类型分配多少空间 < > > C++中的共变返回类型意味着重写返回类型必须是引用或指针。< /P>,c++,inheritance,overriding,virtual,C++,Inheritance,Overriding,Virtual,值类型可以有不同的大小,即使它们共享一个公共基。其中,指针或引用通常是相同的,或者最多是字节移位(虚拟继承或多重继承)。 但是转换值类型可能会导致切片,因为通过副本将较大的类型转换为较小的类型(即使基类型定义了副本构造函数或运算符,它们仍然经常切片,因为没有地方存储派生类添加的任何额外字段) e、 g.假设这是允许的,我有两种类型A和B我想用作X和Y的协变返回 struct A { int x, y; }; struct B : A { int c; }; class X

值类型可以有不同的大小,即使它们共享一个公共基。其中,指针或引用通常是相同的,或者最多是字节移位(虚拟继承或多重继承)。 但是转换值类型可能会导致切片,因为通过副本将较大的类型转换为较小的类型(即使基类型定义了副本构造函数或运算符,它们仍然经常切片,因为没有地方存储派生类添加的任何额外字段)

e、 g.假设这是允许的,我有两种类型
A
B
我想用作
X
Y
的协变返回

struct A
{
    int x, y;
};
struct B : A
{
    int c;
};



class X
{
public:
    virtual A get_a();
};
class Y : public X
{
public:
    B get_a()override;
}
这里的问题是,当使用对
X
的引用时,实际上可能是
Y
我可以这样做:

X *x = new Y();
A a = x->get_a();
但是,通过对实际返回a
B
Y
实例调用
get_a
,它必须隐式地将
B
转换为
a
,但这将“切掉”我的
B::c
成员,这可能会使其处于无效状态(特别是如果
A
具有任何虚拟函数,并且这些函数预期为
B::c
,现在处于对象的“外部”)

在一般情况下,程序员或编译器都无法判断这可能发生在
A A=x->get_A()
行,因为
x
可以被任何东西描述(甚至可能超出编译器的潜在知识范围,例如在单独的DLL中!)

非虚拟情况下,编译器和程序员可以判断它的发生,所以尽管C++允许切片,但至少知道它正在发生,并且可能是编译器警告。

class X
{
public:
    A get_a();
};
class Y : public X
{
public:
    B get_a(); // Not an override!
}
X *x = new Y();
A a = x->get_a(); // still called X::get_a, no slice ever!


Y *y = new Y();
A a = y->get_a(); // calls Y::get_a, which slices, but the compiler and programmer can tell that from static typing.

你用“代码>动物GeMealAlcIn()){返回Cd();} /Cord>。我想它不会那么混乱。“但是当从函数返回时,它很好”C++的问题是,不是所有看起来都很好的东西实际上是好的;看起来从函数返回指针,引用和副本允许您返回协变类型,但如果虚拟方法重写,则只允许您返回指针和引用。奇怪的是,不仅仅是覆盖类型,而且基类中返回类型。有趣的是,关于这个问题的另一个问题是关于C++在虚拟方法的情况下阻止它的原因是调用方不知道在虚拟调用中分配返回空间的空间。