c++面向对象总结

1、为什么要用面向对象的思想去编程?

为了解决缩短开发的时间周期,如何才能缩短开发周期,粘贴复制已有的代码,以前的代码可以修改一下可以直接拿过来用,所以我们要解决的问题就是代码的复用性问题。

如何提高代码的复用性?面向对象的思想,想办法把某些相似相似或者抽象共性的问题直接移植,这就是面向对象的方法。面向对象的产生就是为了提高代码的复用性,满足快速开发的需求。

2、面向对象的精髓?

面向对象包括封装、继承、多态,而继承和多态是面向对象的精髓。

我们的出发点还是提高代码的复用性,而继承可以很直观的体现出来这种特征。对一种类型的所用对象的共性只定义一次,便可以通过继承的方式对基类做无须修改的复用。

比如说我们定义了动物这个大类,我们知道动物有这样的共性,即多以有机物为食料,有神经,有感觉,能运动,假如现在我们要对所有的动物定义一个标明生理特征的方法显示自己的一些特征标签供参观者查看,我们可以在每一类动物类中放置这样一个输出特征标签的函数来表明生理特征,即输出“有神经,有感觉,能运动”,但如果真的为每一种动物去写这样一个表明特征的输出函数,会造成大量没必要的重复,导致效率极低,我们的出发点四提高代码的复用性,那么,我们现在完全可以把这样一个函数放在“动物”这个基类中,通过继承让所有种类的动物都拥有这样具有输出功能的函数,且不做任何修改的继承。这就是继承这种一劳永逸的思想带给我们极大的好处,当我们实现了上述这种非常便捷的继承思想处理问题时,我们在想,我们能不能把所有的问题都归纳成上述这种方式去一劳永逸的便捷的去处理呢?最好是只在基类中写相应的方法,通过继承让其他类直接复用,答案是"NO",
正如世界上没有相同的两片叶子,不管多么类似的对象,它们都有各自的差异性。
我们又要考虑某一类型对象的某些共同特征的差异性,比如说猴类都有毛,但是毛的颜色会有差异,所以在每个对象对定义毛的函数是不同的,如果直接全盘继承基类的同名函数肯定不行,为了便是这种差异化,我们引入了重写机制。当我们尽可能的顾全大局的在基类中放置一些非常通用的函数以供派生类继承使用,从而提高代码的复用性,但是肯定会有个别的有差异的对象不能完全使用继承过来的这个函数,那么,他就会自己定义一个功能非常相似又略有差异的同名函数(同名函数的作用很大意义上是一类相同或者相似操作的标识,这样可以避免在使用接口的时候出现各种功能相同或相似的操作但函数名称却千差万别的情况,给使用者带来困惑,),把基类继承过来的函数屏蔽掉(注意和函数重载的区别),从而很好的解决了个体的细小差异性,而使大部分都可以复用,这就是重写基类。再说说继承这种机制另一个非常好的作用,即代码的可扩展性,不管是基类重写还是派生定义自己的成员,都可以看做是派生类的扩展性。正是这种可扩展性才最大可能的促进了代码的复用性。

那么,又为什么要引进虚函数这种机制呢?
讨论虚函数之前,我们必须清楚面向对象的思想中如何调用子类的特征函数,就是用基类的指针指向派生类对象,然后通过基类指针对象去调用派生类函数。为什么一定要通过基类指针调用子类函数呢?定义派生类指针直接指向自己的函数不是更简单吗?当然不是!!!!!!我们为什么非要用基类指针去指向派生类,然后调用派生类的成员呢
这比如上述提到的动物类,动物都会繁殖,所以我把繁殖方式这种方法写在基类中供派生类继承,但是不同的动物又有不同繁殖方式,所以在我要在派生类中进行重定义,当我把动物类所有的派生对象用一个统一的类型即动物指针类型存储在数组里后,非常有利于对整个类的整体操作减少代码的重复性,但这时我要输出每个动物派生类对象的繁殖方式时,我就得把这个数组里的指针取出来,然后判断到底是哪个派生类型的,在调用他的繁殖方式的函数,这又与前面“操作减少代码的重复性”矛盾,所以我们引进虚函数让他自己判断该调用哪个函数,这正是多态性的体现,同时大大减少的开发量。
  1.   
  2. class Base  
  3. {  
  4. public:  
  5.     void g(float x)  
  6.     {  
  7.         cout<<"Base::g(float)"<< x <<endl;  
  8.     }  
  9. };  
  10.   
  11. class Derived : public Base  
  12. {  
  13. public:  
  14.     void g(int x)  
  15.     {  
  16.         cout<<"Derived::g(int)"<< x <<endl;     //隐藏  
  17.     }  
  18. };  
  19.   
  20. int main(void)  
  21. {  
  22.     // 基类的指针指向子类对象  
  23.     Base *pb = &d;  
  24.   
  25.     // 非虚函数,根据指针属于基类或子类调用  
  26.     pb->g(3.14f);   // Base::g(float)  3.14 基类指针不会调用子类对象
  27.   
  28.     return 0;  
  29. }  


我们发现,当我们需要在派生类中将继承过来的基类的某些方法进行修改以适应派生类的处理要求后(通常采用同名函数的隐藏基类的方法),也就是基类的重写,但当我们用基类指针指向派生类调用函数时,并不会调用派生类重定义的函数(这是因为基类不能调用派生类成员),这个显然不是我们想要的,这时我们就要把基类指针显式的强制转化成相应的派生类指针,然后才会调用派生类的重定义函数,这样会非常繁琐,那么,我们可不可以有这么一种机制,当基类指针指向他的派生类对象调用某一特定的函数时,会优先自动调用该派生类的这个函数,如若该派生类没有这个函数,他会自动沿着继承链向上爬,找到这个同名函数停止,这个方法正是虚函数给我们解决的。



猜你喜欢

转载自blog.csdn.net/libaoshan55/article/details/78262027