c++ - 小心从派生类到基类的转换 (ptr Vs. obj)
来源:互联网 发布:网络视听审核员怎么考 编辑:程序博客网 时间:2024/05/16 15:23
将一个派生类指针或引用赋给基类指针或引用是安全的且自动转换的;将一个派生类对象赋给基类对象将发生“切割”(sliced),是不正确的写法!
由于Son对象包含了一个Base对象,因此用一个Son对象去初始化Base对象时,实际上是将自身的Base类部分拷贝构造新的Base对象,而新的Base对象没有Son类成员的存储空间,因此将Son类的成员丢弃,即“切割”。此外,虽然新的Base对象已经copy了Son对象的Base这部分数据,但是虚表并没有更新(还是Son的虚表)。也就是说,这里有两个大隐患。
相反,将一个Son对象的指针赋给Base类的指针时,只是把Son对象的地址拷贝给一个指针类型的变量,并没有发生对象拷贝操作或者改变原来的对象。
看看下面的例子
void FunPtr(Base*);
void FunVal(Base );
//...
Base* basePtr = new Base();
Son * sonPtr = new Son();
//...
FunPtr( sonPtr); //No problem
FunPtr( basePtr); //NP
FunVal(*sonPtr); //wrong: sliced!!!
FunVal(*basePtr); //NP from the view of syntax, but has a performance problem
//for passing parameters by values,it will trigger a copy constructor
//...
Base base(*sonPtr); //Wrong: sliced!!!
Son son;
//...
*basePtr = son; //Wrong: sliced!!!
从上面的例子可知,如果在函数的参数列表中使用pass by value,要注意避免使用有继承关系的类;通常只有build in类型或者structure类型才不会有本文中的问题。
除了自己留意,避免这种错误外,有没有根本的解决之道呢?
如果一个类可以被继承,完全可以根据“按接口编程”的思想,提取一个接口;这在c++中就是纯虚基类。如果没必要纯虚,也可以把基类作为一个抽象类。因为抽象类不能实例化,那么上面的3处错误可以在编译期就被发现,而不是运行态:借用一句名言,能被编译器发现的问题不是问题!
扩展开来讲,具体类不适合作为基类,抽象类更合理。这个不仅仅有设计上的必要,也有实践上的意义(就是本文中所述的)
- c++ - 小心从派生类到基类的转换 (ptr Vs. obj)
- OBJ-C类的继承和派生学习笔记
- 派生类到基类的转换
- 派生类到基类的转换
- C++ 从基类到派生类的转换
- 派生类到基类的转换 和基类到派生类的转换
- 派生类到基类的转换 和基类到派生类的转换
- 派生类到基类的转换 和基类到派生类的转换
- Char** ptr 到Char*的转换
- 派生类到基类转换的可访问性
- 派生类到基类转换的可访问性
- 二十六、继承(三) 转换与继承、派生类到基类的转换、基类到派生类的转换
- 【c++】实例演示类继承中派生类到基类的转换及虚函数
- 派生类到基类的转换(c++学习笔记)
- 派生类到基类的转换(c++学习笔记)
- 《C++ Primer》派生类到基类转换的可访问性
- c++ 初学 派生类到基类转换的可访问性
- C++ 派生类到基类转换的可访问性
- QT学习 第一章:基本对话框--实现QQ抽屉效果
- 新人职场浅规则
- apache&&php安装
- View Controller Basics
- Windows Mobile模拟器上网设置
- c++ - 小心从派生类到基类的转换 (ptr Vs. obj)
- linux下运行perl
- IT外企那点儿事(1):外企也就那么回事
- 两个小时学会DirectDraw编程 (转)
- Solution of ZOJ 1205 Martian Addition
- dojo学习
- Flume 学习笔记 一 : Flume User Guide
- 国内首套物联网专业丛书《物联网核心技术丛书》已经出版
- 一个链表创建、反转、打印的C语言代码