C ++:“无效协变量返回类型”返回基于模板对象的方法的嵌套类中的错误 [英] C++: "Invalid covariant return type" errors in nested classes with methods returning template-based objects

查看:151
本文介绍了C ++:“无效协变量返回类型”返回基于模板对象的方法的嵌套类中的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下C ++代码在编译时给出了这些错误:

  covariant.cpp:32:22:error:invalid covariant '虚拟Q< B>的返回类型C :: test()'
covariant.cpp:22:22:error:overriding'virtual Q< B :: test()'

我不想更改虚拟Q B test(){} virtual Q< test(){} ,虽然它删除了编译错误。有没有其他方法来解决这个问题?

 模板< 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< B& / code>和 Q< A> 是不相关的类。假设你是 B 调用 test()的客户端:你将结果分配给什么知道它将要有什么类型?



事实上, Q< A> 是相同类模板的实例不改变它们是两个完全不相关的类的事实,可能具有完全不同的布局(由于模板专用化)。



这不会有什么不同:

  struct X 
{
virtual std :: string test()= 0;
};

struct Y:X
{
virtual int test(){return 42; } //错误! std :: string和int是
//不相关的,就像Q< A>和Q B。
};

客户端调用 test()指向 X 的指针会期望结果是 string ,但是Whoops!指针是 Y 类型, Y :: test()的返回类型是 INT 。会发生什么?运行时崩溃?

  Y y; 
X * p =& y;
std :: string s = p-> test(); // D'OH!

C ++是一种静态类型语言,意味着类型检查在编译时执行。在这种情况下,编译器的消息是告诉你派生类不坚持它派生自的类的接口。



如果你想知道什么无效的协变返回类型,特别是 covariant



假设你有一个带有虚函数 foo()的基类 B ,返回 X *

  struct B 
{
virtual X * foo );
};

假设你有一个类 D 通过返回 Y * foo() B c>,其中 Y 是从 X 中派生的类:

  struct D:B 
{
virtual Y * foo();
};

这是一个问题吗?好的,正确的答案来自回答这个稍微好一些的问题:这将是一个客户调用 foo()的问题,期望一个 X * 要返回?



这个问题的答案显然是否 $ c> Y X 的派生类,因此可以返回 Y $
B * b =& d;
X * p = b-> foo(); //返回一个Y *,但是没关系,因为指向Y的指针可以是
//分配给指向X
的指针

这是协变返回类型的示例。在你的例子中, C :: test()的返回类型对于 B :: test()的返回类型不是协变的


The following C++ code gives me these errors when compiled:

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()’

I do not want to change the line virtual Q<B> test() {} to virtual Q<A> test() {} although it removes the compilation errors. Is there another way to solve this problem?

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<B> and Q<A> are unrelated classes. Imagine you are a client of B calling test(): what do you assign the result to, if you do not know what type it is going to have?

The fact that both Q<A> and Q<B> are instances of the same class template does not change the fact that they are two completely unrelated classes, possibly with a completely different layout (due to template specialization).

This would not be any different from doing:

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>
};

The client calling test() on a pointer to X would expect the result to be a string, but "Whoops!", the object pointed to by that pointer is of type Y, and the return type of Y::test() is int. What should happen? A run-time crash?

Y y;
X* p = &y;
std::string s = p->test(); // D'OH!

C++ is a statically typed language, meaning that type checking is performed at compile-time. In this case, the message from the compiler is there to tell you that the derived class does not adhere to the interface of the class it derives from.

If you are wondering what "invalid covariant return type" means, and in particular the word "covariant", that's easily explained.

Suppose you have a base class B with a virtual function foo() that returns an X*:

struct B
{
    virtual X* foo();
};

And suppose that you have a class D derived from B that overrides foo() by returning an Y*, where Y is a class derived from X:

struct D : B
{
    virtual Y* foo();
};

Is this a problem? Well, the right answer comes from answering this slightly better question: "Would that be a problem for a client calling foo() that expects an X* to be returned?"

And the answer to that question is obviously "No", since Y is a derived class of X, so you can return a pointer to Y instead of a pointer to X:

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

This is an example of a covariant return type. In your example, the return type of C::test() is not covariant with respect to the return type of B::test().

这篇关于C ++:“无效协变量返回类型”返回基于模板对象的方法的嵌套类中的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆