&引用;无效的协变返回类型“;方法返回基于模板的对象的嵌套类中的错误 编译后的C++代码给我这些错误: covariant.cpp:32:22: error: invalid covariant return type for ‘virtual Q<B> C::test()’ covariant.cpp:22:22: error: overriding ‘virtual Q<A> B::test()’ 协变.cpp:32:22:错误:“virtual Q C::test()的协变返回类型无效” 协变.cpp:22:22:错误:重写“virtual Q B::test()”
我不想将行&引用;无效的协变返回类型“;方法返回基于模板的对象的嵌套类中的错误 编译后的C++代码给我这些错误: covariant.cpp:32:22: error: invalid covariant return type for ‘virtual Q<B> C::test()’ covariant.cpp:22:22: error: overriding ‘virtual Q<A> B::test()’ 协变.cpp:32:22:错误:“virtual Q C::test()的协变返回类型无效” 协变.cpp:22:22:错误:重写“virtual Q B::test()”,c++,class,templates,nested,covariant,C++,Class,Templates,Nested,Covariant,我不想将行virtualqtest(){}更改为virtualqtest(){},尽管它会删除编译错误。还有别的办法解决这个问题吗 template <class T> class Q { public: Q() {} virtual ~Q() {} }; class A { public: A() {} virtual ~A() {} }; class B { public:
virtualqtest(){}
更改为virtualqtest(){}
,尽管它会删除编译错误。还有别的办法解决这个问题吗
template <class T>
class Q
{
public:
Q() {}
virtual ~Q() {}
};
class A
{
public:
A() {}
virtual ~A() {}
};
class B
{
public:
B() {}
virtual ~B() {}
virtual Q<A> test() = 0;
};
class C : public B
{
public:
C() {}
virtual ~C() {}
virtual Q<B> test() {}
};
模板
Q类
{
公众:
Q(){}
虚拟~Q(){}
};
甲级
{
公众:
A(){}
虚拟~A(){}
};
B类
{
公众:
B(){}
虚拟~B(){}
虚拟Q测试()=0;
};
丙类:公共乙类
{
公众:
C(){}
虚拟~C(){}
虚拟Q测试(){}
};
带有签名的函数B::test(void)
返回类型为Q
的对象,而C::test(void)
(这是相同的签名,因此您正在覆盖函数)返回Q
。我认为那是不可能的
据我所知,不可能按返回类型重载函数,父函数的重写需要使用相同的返回类型
根据标准§10.3/7
重写函数的返回类型应与重写函数的返回类型相同,或与函数类共变。如果函数D::f重写函数B::f,则函数的返回类型是协变的,前提是它们满足以下条件:
- 两者都是指向类的指针,都是对类的左值引用,或者都是对类的右值引用 类别112
- B::f的返回类型中的类与D::f的返回类型中的类相同,或者是D::f的返回类型中的类的明确且可访问的直接或间接基类
- 两个指针或引用都具有相同的cv限定,并且D::f的返回类型中的类类型具有与B::f的返回类型中的类类型相同的cv限定,或者小于B::f的返回类型中的类类型
签名为
B::test(void)
的函数返回类型为Q
的对象,而C::test(void)
(这是相同的签名,因此您正在覆盖函数)返回Q
。我认为那是不可能的
据我所知,不可能按返回类型重载函数,父函数的重写需要使用相同的返回类型
根据标准§10.3/7
重写函数的返回类型应与重写函数的返回类型相同,或与函数类共变。如果函数D::f重写函数B::f,则函数的返回类型是协变的,前提是它们满足以下条件:
- 两者都是指向类的指针,都是对类的左值引用,或者都是对类的右值引用 类别112
- B::f的返回类型中的类与D::f的返回类型中的类相同,或者是D::f的返回类型中的类的明确且可访问的直接或间接基类
- 两个指针或引用都具有相同的cv限定,并且D::f的返回类型中的类类型具有与B::f的返回类型中的类类型相同的cv限定,或者小于B::f的返回类型中的类类型
Q
和Q
是不相关的类。假设您是B
调用test()
的客户机:如果您不知道结果的类型,您会将结果分配给什么
Q
和Q
都是同一类模板的实例,这一事实并不改变这一事实,即它们是两个完全不相关的类,可能具有完全不同的布局(由于模板专门化)
这与执行以下操作没有任何区别:
struct X
{
virtual std::string test() = 0;
};
struct Y : X
{
virtual int test() { return 42; } // ERROR! std::string and int are
// unrelated, just as Q<A> and Q<B>
};
C++是一种静态类型语言,这意味着类型检查是在编译时执行的。在本例中,来自编译器的消息告诉您派生类不符合它派生的类的接口
如果您想知道“无效协变返回类型”是什么意思,特别是“协变”一词,那么很容易解释
假设您有一个基类B
,其中有一个返回X*
的虚拟函数foo()
:
struct B
{
virtual X* foo();
};
假设您有一个从B
派生的类D
,它通过返回Y*
来覆盖foo()
,其中Y
是从X
派生的类:
struct D : B
{
virtual Y* foo();
};
D d;
B* b = &d;
X* p = b->foo(); // Returns an Y*, but that's OK, because a pointer to Y can be
// assigned to a pointer to X
这是个问题吗?正确的答案来自于回答这个稍微好一点的问题:“对于调用foo()
并期望返回X*
的客户机来说,这会是个问题吗?”
这个问题的答案显然是“否”,因为Y
是X
的派生类,所以您可以返回指向Y
的指针,而不是指向X
的指针:
struct D : B
{
virtual Y* foo();
};
D d;
B* b = &d;
X* p = b->foo(); // Returns an Y*, but that's OK, because a pointer to Y can be
// assigned to a pointer to X
这是协变返回类型的一个示例。在您的示例中,C::test()
的返回类型与B::test()的返回类型不一致 Q
和Q
是不相关的类。假设您是B
调用test()
的客户机:如果您不知道结果的类型,您会将结果分配给什么
Q
和Q
都是同一类模板的实例,这一事实并不改变这一事实,即它们是两个完全不相关的类,可能具有完全不同的布局(由于模板专门化)
这与执行以下操作没有任何区别:
struct X
{
virtual std::string test() = 0;
};
struct Y : X
{
virtual int test() { return 42; } // ERROR! std::string and int are
// unrelated, just as Q<A> and Q<B>
};
C++是一种静态类型的语言,这意味着该类型是che