aka*_*ppa 4 c++ inheritance pointers
好吧,我正在阅读FQA中关于将a转换Derived**为a Base**以及为什么禁止它的问题的这篇条目.我得到的问题是你可以分配给一个Base*不是a 的东西Derived*,所以我们禁止这样做.
到现在为止还挺好.
但是,如果我们深入应用这一原则,为什么我们不禁止这样的例子呢?
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?
}
Run Code Online (Sandbox Code Playgroud)
我同意nasty_function做一些愚蠢的事情,所以我们可以说让这种转换很好,因为我们启用了有趣的设计,但我们可以说也是为了双重间接:你有一个Base **,但你不应该给它任何东西尊重,因为你真的不知道它到底在哪里,Base **就像Base *.
所以,问题是:间接的额外级别有什么特别之处?也许重点是,只有一个间接层,我们可以使用虚拟operator=来避免这种情况,而普通指针上没有相同的机制吗?
R. *_*des 15
nasty_function(d); // Ooops, now *d points to a Base. What would happen now?
Run Code Online (Sandbox Code Playgroud)
不,它没有.它指向一个Derived.该函数只是更改Base了现有Derived对象中的子对象.考虑:
#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);
}
Run Code Online (Sandbox Code Playgroud)
d不是神奇地变成了Base,是吗?它仍然是一个Derived,但它的Base一部分发生了变化.
在图片:)
这是Base和Derived物体的样子:

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

注意如何尝试改变所讨论的对象Base或Derived对象:只有中间指针是.
但是,当你只有一个间接层时,代码会以对象允许的方式修改对象本身(它可以通过私有,隐藏或删除赋值运算符来禁止它Base):

请注意这里没有更改指针.这就像改变对象的一部分的任何其他操作一样d.y = 42;.
不,nasty_function()不像听起来那么令人讨厌.当指针b指向的东西是,一 Base,这是完全合法的分配Base-值给它.
请注意:您的"Ooops"评论不正确:d仍然指向Derived与通话前相同的评论!只是,Base它的一部分被重新分配(按价值!).如果这让你的整体Derived不稳定,你需要通过Base::operator=()虚拟重新设计.然后,nasty_function()实际上Derived将调用赋值运算符(如果已定义).
所以,我认为,你的例子与指针到指针的情况没那么多.