一、常识
随意打开一本C++书,基本都会写着一句话:子对象可以转化成父对象,父对象不能转化成子对象。
1.1、子对象可以转化成父对象
很好理解,其实就是C++多态的体现,父指针可以指向子对象地址,当调用父对象里生命的函数时,会默认调用子对象的此“重写函数”巴拉巴拉巴拉.....
1.2、父对象不可转化成子对象
存在即道理,这句话其实是想说明,子对象的属性或者函数大多情况下比父对象更丰富,即父亲有的东西一定会传儿子,儿子有的东西父亲不一定有【这个比喻显然不符合百善孝为先的老百姓,但C++是没有感情的东西】,如果我们将父对象转化成了子对象,那么这个对象势必会无缘无故多了一些原本不存在的属性或者函数,如果这些属性里包含一些指针或者堆上或者特有的东西,在访问的时候程序基本就崩了,就出现了程序员的老熟人“野指针”、“内存泄露”....
用一个例子:
class Parent{ double money; }; class Son : public Parent{ Girl* girl = new Girl; }; main(){ Parent parent; Son* son = &parent; son->girl; }
如上代码:
父亲只有钱,儿子继承了父亲的钱,并且儿子还有Beautiful Girl,但是此时的实体是父亲【只有钱没有Beautiful Girl】,然后拿着儿子的身份证【接口】去访问Beautiful Girl,结果GG找不到
二、误解
2.1、现象
随意在Bing【强烈抵制Baidu】搜索C++父子类之间的转换,发现又能找到很多的方法,那这又是为什么呢?包括平时都或多或少的用到了父类转子类的方式如:在Qt界面是将一个按钮嵌入到Table里,然后又拿出来强转成按钮使用....
2.2、不多bb直接放结论:
严格意义上父类是能转化成子类的,但有限制条件,一旦不注意就会程序崩溃,不建议使用。
2.3、讨论之前需要放两个概念:
Parent* p = new Son;
①、指针对象
p,就是指针,根据多态,可以是父指针也可以是子指针。【一般父指针多得多,多态嘛】
②、对象实体
new Son,也就是new出来或者最后调用构造函数的对象【根据父子子父的顺口溜,可以知道最后调用哪个对象的构造函数,那这个对象就是最终的子类实体】
2.4、适用现象
为什么我说父类是能转化成子类的呢,是因为我们直接用父指针来指向子对象,代码是能编译过的,但是不能用父指针去获取不属于自己的属性或内存片。
所以当父指针不会跨界去访问不属于自己的东西的时候,是没问题的。
2.5、解释神奇现象
上面提到平时Qt的一些操作,这个操作虽然用的很多,但是讨论这篇文章的时候,同事提出来这个现象,我一时不知如何解释,感觉多年的C++基础知识突然崩塌了.....
后来想了想,应该是这样的步骤:
①、new出子类对象实体,用父指针指向
②、通过父指针将子类对象实体设置到界面上
③、通过父指针从界面上获取子类对象实体
④、通过static_cast将【父指针指向的】子类对象实体转成子类
其实整个过程都是子类对象实体,根本没有父对象实体,所以这里根本不是父对象转化成子对象,就是子对象的转来转去,只不过用父指针的访问罢了。