协变回报类型给我们带来了什么? [英] What do covariant return types buy us?

查看:48
本文介绍了协变回报类型给我们带来了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑经典的clone()函数:


class A {

public:

virtual~A(){ }

虚拟A * clone()const = 0;

};


B类:公共A {

public:

//由于协变返回而覆盖A :: clone():

B * clone()const {return new B(* this ); }

};


//等等


如果我存储clone()的返回值在一个指针的容器中,这对我来说是没收的,因为从B *到A *有一个隐含的转换

。实际上,对于不支持协变回报类型的编译器,我可以通过将B :: clone()的返回类型声明为A *来完全相同。


我确定有理由允许这样做,但我似乎无法确定

我想出了一个具体的例子需要这个做点什么我不会在一个没有实现它的编译器上做b $ b。


-

Bob Hairgrove
没有********** @ Home.com


[见 http:/ /www.gotw.ca/resources/clcm.htm 了解有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]

Consider the classic clone() function:

class A {
public:
virtual ~A() {}
virtual A* clone() const = 0;
};

class B : public A {
public:
// overrides A::clone() due to covariant return:
B* clone() const { return new B(*this); }
};

// etc.

If I am storing the return value of clone() in a container of pointers
to A, this buys me nothing, because there is an implicit conversion
from B* to A*. Indeed, with compilers which do not support covariant
return types, I can do exactly the same by declaring the return type
of B::clone() as A*.

I''m sure there was a reason for allowing this, but I can''t seem to
come up with a concrete example of how I need this to do something I
couldn''t do on a compiler which doesn''t implement it.

--
Bob Hairgrove
No**********@Home.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

推荐答案

* Bob Hairgrove:
* Bob Hairgrove:
考虑经典的clone()函数:

A级{
公开:
虚拟~A(){}
虚拟A * clone()const = 0;
};

B类:public A {
public:
//由于协变返回而覆盖A :: clone():
B * clone()const {return new B(* this) ; }

//

如果我将clone()的返回值存储在A的指针容器中,这没有给我买任何东西,因为从B *到A *有一个隐含的转换。实际上,对于不支持协变返回类型的编译器,我可以通过将B :: clone()的返回类型声明为A *来完全相同。

我确定有理由允许这样做,但我似乎无法想出一个具体的例子,说明我需要做什么才能做我无法做的事情。一个没有实现它的编译器。
Consider the classic clone() function:

class A {
public:
virtual ~A() {}
virtual A* clone() const = 0;
};

class B : public A {
public:
// overrides A::clone() due to covariant return:
B* clone() const { return new B(*this); }
};

// etc.

If I am storing the return value of clone() in a container of pointers
to A, this buys me nothing, because there is an implicit conversion
from B* to A*. Indeed, with compilers which do not support covariant
return types, I can do exactly the same by declaring the return type
of B::clone() as A*.

I''m sure there was a reason for allowing this, but I can''t seem to
come up with a concrete example of how I need this to do something I
couldn''t do on a compiler which doesn''t implement it.




考虑在B中你需要(1)覆盖A :: clone,并且(2)提供一个

B特定指向直接使用B的客户端的指针。如果编译器没有支持协变类型,那么就会涉及B'代码中的向下转换,

。 Covariance可以帮助你避免这种情况,无可否认的是,在每个具体的情况下都能证明是正确的,而且是低价的。


另一方面,协方差只能让你免于当

结果类型是原始指针或引用时,向下转换;对于智能指针结果

你没有保存,但必须自己动手。


使智能指针更像Java / C#引用我们需要 -

呃,某事。现在已经很晚了。但是我记得在考虑这个问题

这就是问题的关键所在。粗略地说。

-

A:因为它弄乱了人们通常阅读文字的顺序。

问:为什么这么糟糕?

A:热门帖子。

问:usenet和电子邮件中最烦人的是什么?


[见 http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang .C ++。主持。第一次海报:做到这一点! ]



Consider that in B you need to (1) override A::clone, and (2) provide a
B-specific pointer to clients using B directly. If the compiler doesn''t
support covariant types, that involves a downcast in B''s code,
somewhere. Covariance saves you from that, admittedly trivial and easy
to prove correct in each concrete case, downcast.

On the other hand, covariance only saves you from the downcast when the
result type is a raw pointer or reference; for a smart pointer result
you''re not saved, but have to Do It Yourself.

To make smart pointers work more like Java/C# references we''d need --
uh, something. It''s late in my day. But I remember thinking about it
and that''s where the crux of the matter is located, roughly.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Bob Hairgrove写道:
Bob Hairgrove wrote:

我确定有理由允许这样做,但我似乎无法想出一个具体的例子,说明我是如何做一些我无法在没有实现它的编译器上做的事情。

I''m sure there was a reason for allowing this, but I can''t seem to
come up with a concrete example of how I need this to do something I
couldn''t do on a compiler which doesn''t implement it.




当你知道你有一个指向B的指针时,你可以得到另一个指向B的指针:


B * ptr1 =新B;

B * ptr2 = ptr1->克隆();


-


Pete Becker

Roundhouse Consulting,Ltd。


[见 http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang.c ++ .moderated。第一次海报:做到这一点! ]



When you know you''ve got a pointer to B, you can get another pointer to B:

B *ptr1 = new B;
B *ptr2 = ptr1->clone();

--

Pete Becker
Roundhouse Consulting, Ltd.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Bob Hairgrove写道:
Bob Hairgrove wrote:
考虑经典的clone()函数:

A类{
公开:
虚拟~A(){}
虚拟A * clone()const = 0;
};

B类:公共由于协变返回,公共:
//覆盖A :: clone():B * clone()const {return new B(* this); }

//

如果我将clone()的返回值存储在A的指针容器中,这没有给我买任何东西,因为从B *到A *有一个隐含的转换。实际上,对于不支持协变返回类型的编译器,我可以通过将B :: clone()的返回类型声明为A *来完全相同。

我确定有理由允许这样做,但我似乎无法想出一个具体的例子,说明我需要做什么才能做我无法做的事情。一个没有实现它的编译器。
Consider the classic clone() function:

class A {
public:
virtual ~A() {}
virtual A* clone() const = 0;
};

class B : public A {
public:
// overrides A::clone() due to covariant return:
B* clone() const { return new B(*this); }
};

// etc.

If I am storing the return value of clone() in a container of pointers
to A, this buys me nothing, because there is an implicit conversion
from B* to A*. Indeed, with compilers which do not support covariant
return types, I can do exactly the same by declaring the return type
of B::clone() as A*.

I''m sure there was a reason for allowing this, but I can''t seem to
come up with a concrete example of how I need this to do something I
couldn''t do on a compiler which doesn''t implement it.




考虑你有一个B指针容器的情况,你需要b $ b b希望通过克隆一些B类对象来填充。如果B'的clone()方法没有协变

返回类型,你就无法将B

克隆的指针放在容器中;因为克隆B类对象获得的A类指针

不是正确的类型。


关于解决这个问题的唯一方法就是 ;垂头丧气" A

指针。但是,向下转型是一个没有吸引力的解决方案。人们普遍认为,一般情况下,一般情况下看来是一个糟糕的编程习惯,但更糟糕的是 - 一个

的低迷并不能保证能够正常工作。在向下转换

时,返回clone的指针。例程可能看似安全无害,关于类的其他虚拟方法返回的指针是什么?b $ b?对于

哪些可以将返回的指针向下转换,哪些不可以?


如果没有协变返回类型,答案是客户端只是

必须知道当一个方法返回指向声明的一个子类的指针时 - 客户端是否需要该信息。因为

这里的问题是方法的声明只是部分

正确 - 要获得完整的信息,需要某种

特别安排。这种安排允许客户端忽略

方法的声明返回类型,并且能够确定将返回指向子类对象的指针




但正是这些类型的侧面安排 - 需要

信息可以在声明的界面之外的某处找到

- 使软件程序难以维护 - 几乎总是

- 最终导致某些事情破裂。所以协变返回类型简单地确定信息不足。通过广告宣传的返回类型,一个程序不再需要通过执行可疑的向下倾斜或通过学习

来弥补丢失的

信息。接口实现的细节。


格雷格

[见 http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang。 C ++。主持。第一次海报:做到这一点! ]



Consider the case in which you have a container of B pointers which you
wish to populate by cloning some class B objects. Without a covariant
return type for B''s clone() method, you would not be able to put the B
clones'' pointers in the container; because the class A pointers
obtained from cloning the B class objects are not the right type.

And about the only way around this problem would be to "downcast" the A
pointers. But downcasting is an unattractive solution. Downcasts in
general are widely viewed as a poor programming practice, but worse - a
downcast is not always guaranteed to work. And while downcasting the
returned pointer of a "clone" routine may seem safe and harmless, what
about the pointers returned by the class'' other virtual methods? For
which can the returned pointer be downcast, and for which can it not?

Without covariant return types, the answer is that the client simply
has to "know" when a method returns a pointer to a subclass of the one
declared - should the client have need for that information. Because
the problem here is that the method''s declaration is only partially
correct - to get the complete information, requires some kind of
special arrangement be made. This arrangement lets a client ignore a
method''s declared return type and be able to be certain that a pointer
to a subclassed object will be returned instead.

But it is precisely these kinds of side arrangements - in which needed
information is to be found somewhere outside of the declared interface
- that make software programs difficult to maintain and - almost always
- eventually cause something to break. So covariant return types simply
correct a deficit of information. With the return type accurately
advertised, a program no longer has to compensate for the missing
information by performing questionable downcasts or by learning the
particulars of an interface''s implementation.

Greg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


这篇关于协变回报类型给我们带来了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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