我有以下代码:
#include <iostream>
using namespace std;
class Child1
{
int i;
};
class Child2 : public Child1
{
int j;
};
class Base1
{
public:
virtual Child1& getChildren()
{
cout << "Children1" << endl;
return children;
}
private:
Child1 children;
};
class Base2 : public Base1
{
public:
virtual Child2& getChildren()
{
cout << "Children2" << endl;
return children;
}
private:
Child2 children;
};
这段代码编译得很好但是当我在getChildren()
和Base1
中的一个或两个中将Base2
的返回类型从引用类型更改为对象类型时(例如virtual Child2 getChildren()
)在Visual Studio 2010上收到以下错误:
error C2555: 'Base2::getChildren': overriding virtual function return type differs and is not covariant from 'Base1::getChildren'
我想知道为什么我不在使用引用时会出现此错误,否则会得到此错误。这是VS2010中的错误吗?因为C ++标准(根据微软网站上的this页面)说的是:重写函数的返回类型应该与被覆盖函数的返回类型相同,或者与类的属性相同。函数。和 B :: f的返回类型中的类与D :: f的返回类型中的类是同一个类,或者是类的明确的直接或间接基类在D :: f的返回类型中,可以在D。
中访问P.S。我目前无法访问该标准,因此无法验证上述报价。
答案 0 :(得分:15)
你错过了他们引用的另一部分:“如果函数D :: f覆盖函数B :: f,如果它们满足以下条件,函数的返回类型是协变的:(1)两者都是指针到类或引用到类“
答案 1 :(得分:4)
它们必须是引用或指针,而不是具体的类。这些要求可以在您的MS报价中的“可变性”规定内幸福地生活。第二部分讲述了“返回类型中的类” - 请注意他们避免“返回类”的关注,因为它是指针或类引用返回类型的类组件。
考虑协方差是什么:你要找回一个对象,为基类编写的一些现有代码可能希望处理它,但是通过虚拟调度最终得到你的一个对象。如果它们的大小不同,那么如何存储对象?这个混乱被间接所包围......你可以决定它们的位置(一些缓冲区,共享内存,堆),协变返回类型是指针或引用。
答案 2 :(得分:0)
如果要将字符串转换(如std :: string)更改为std :: wstring或虚函数的任何字符串转换,则需要更改该虚拟函数的超类,其中实际声明了该虚函数。您需要更改使用函数的每个位置,以便更改字符串转换。
在我的情况下,发生了希望它会帮助一些人......