将派生**转换为基本**和派生*转换为基本* [英] Converting Derived** to Base** and Derived* to Base*

查看:115
本文介绍了将派生**转换为基本**和派生*转换为基本*的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我正在阅读 FQA中的此条目 a>处理将 Derived ** 转换为 Base ** 以及为什么它被禁止的问题;我得到的问题是,你可以分配一个基础* 不是一个 Derived * 禁止。

Ok, I was reading through this entry in the FQA dealing about the issue of converting a Derived** to a Base** and why it is forbidden, and I got that the problem is that you could assign to a Base* something which is not a Derived*, so we forbid that.

到目前为止,这么好。

但是,如果我们深入地应用这个原则,我们禁止这样的例子?

But, if we apply that principle in depth, why aren't we forbidding such example?

void nasty_function(Base *b)
{
  *b = Base(3); // Ouch!
}

int main(int argc, char **argv)
{
  Derived *d = new Derived;
  nasty_function(d); // Ooops, now *d points to a Base. What would happen now?
}

我同意 nasty_function 做一些愚蠢的事情,所以我们可以说,让那种转换是好的,因为我们启用有趣的设计,但我们可以说,也为双重间接:你有一个 Base ** ,但你不应该给它的引用分配任何东西,因为你真的不知道 Base ** 到哪里,就像 Base *

I agree that nasty_function does something idiotic, so we could say that letting that kind of conversion is fine because we enable interesting designs, but we could say that also for the double-indirection: you got a Base **, but you shouldn't assign anything to its deference because you really don't know where that Base ** comes, just like the Base *.

所以,问题:什么是特殊的额外级间接?也许关键是,只需要一个间接级别,我们可以使用虚拟 operator = 来避免这种情况,而同样的机制不可用于普通指针? / p>

So, the question: what's special about that extra-level-of-indirection? Maybe the point is that, with just one level of indirection, we could play with virtual operator= to avoid that, while the same machinery isn't available on plain pointers?

推荐答案

nasty_function(d); // Ooops, now *d points to a Base. What would happen now?

不,它指向派生。该函数简单地更改了现有 Derived 对象中的 Base 子对象。请考虑:

No, it doesn't. It points to a Derived. The function simply changed the Base subobject in the existing Derived object. Consider:

#include <cassert>

struct Base {
    Base(int x) : x(x) {}
    int x;
};
struct Derived : Base {
     Derived(int x, int y) : Base(x), y(y) {}
     int y;
};

int main(int argc, char **argv)
{
  Derived d(1,2); // seriously, WTF is it with people and new?
                  // You don't need new to use pointers
                  // Stop it already
  assert(d.x == 1);
  assert(d.y == 2);
  nasty_function(&d);
  assert(d.x == 3);
  assert(d.y == 2);
}

d t magically成为 Base ,是吗?它仍然是派生,但 Base 部分更改了。

d doesn't magically become a Base, does it? It's still a Derived, but the Base part of it changed.

在图片中:)

这是 Base Derived 对象如下所示:

当我们有两个间接级别时,它不工作,因为被分配的东西是指针:

When we have two levels of indirection it doesn't work because the things being assigned are pointers:

请注意,尝试更改 Base Derived 对象:只有中间的指针。

Notice how neither of the Base or Derived objects in question are attempted to be changed: only the middle pointer is.

但是,当你只有一个间接层次,代码修改对象本身,在对象允许的方式禁止通过从 Base 中隐藏,隐藏或删除赋值运算符):

But, when you only have one level of indirection, the code modifies the object itself, in a way that the object allows (it can forbid it by making private, hiding, or deleting the assignment operator from a Base):

注意没有指针被改变这里。这类似于改变对象的一部分的任何其他操作,例如 d.y = 42;

Notice how no pointers are changed here. This is just like any other operation that changes part of an object, like d.y = 42;.

这篇关于将派生**转换为基本**和派生*转换为基本*的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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