重载和覆盖

重载(overloding)和覆盖(overriding)这两个词语对于学习OO开发的人应该不会陌生,也不应该陌生,相反的而应该将这两个的区别弄的一清二楚,话说,其实当年在学习的时候对这两个的的更深入的内容不是很清楚。

重载是出现在同一个类中的就是函数名一样,而参数个数和类型不一样的,而覆盖是出出现在子类中的,子类用来覆盖父类中的同名函数,这几句话是老师苦口婆心交给我们的,而则两句似乎也成了口头禅。

多年以后,仔细品味身边的书籍,有一种突如其来的想法,想自己写一写东西,还是看下面的一个例子:

#include <stdio.h> 
#include <iostream> 
  
/**  
*Shape 
*/
class CShape 
{ 
public: 
CShape(){} 
virtual ~CShape(){} 
  
virtual void Draw()

{

printf("Hello! I am Base!/n");


}

}; /** *Point */ class CPoint : public CShape { public: CPoint(){} ~CPoint(){} void Draw() { printf("Hello! I am Point!/n"); } }; /** *Line */ class CLine : public CShape { public: CLine(){} ~CLine(){} void Draw() { printf("Hello! I am Line!/n"); } }; void main() { CShape* shape = new CPoint(); //draw point shape->Draw();//在这里shape将会调用CPoint的Draw()函数 delete shape; shape = new CLine(); //draw Line shape->Draw();//而在这里shape将会调用CLIne 的Draw()函数 delete shape; return ; }

同一个父类调用同一个方法,结果却是不一样,当然这是我们想要的结果,这种在OOP叫做多态,OO的三大特性之一就有多态这个说法。
多态:字面的含义是具有多种形式或形态。C++多态有两种形式,动态多态和静态多态;动态多态是指一般的多态,是通过类继承和虚函数机制实现的多态;静态多态是通过模板来实现,因为这种多态实在编译时而非运行时,所以称为静态多态。

动态多态是我们常用的,其是在运行阶段进行时确定函数的调用,在C++中要达到这个效果,就要使用虚函数,有一个词语,叫迟后绑定或者运行时绑定或者晚绑定,说的就是这个;静态多态是在编译阶段将函数的调用关系就确定了,因此也叫早绑定。

其实这两个过程也就是高级语言的两个过程,编译和运行,至于这两个过程分别做些什么处理,计算机的书籍上都有很详细的介绍,我也就不罗嗦了。

在C++中实现这种动态多态常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。

如果不用虚函数,实际会是什么样子呢?

#include <stdio.h> 
#include <iostream> 
  
/**  
*Shape 
*/
class CShape 
{ 
public: 
CShape(){} 
virtual ~CShape(){} 
  
 void Draw()

{
printf("Hello! I am Base!/n");

} }; /** *Point */ class CPoint : public CShape { public: CPoint(){} ~CPoint(){} void Draw() { printf("Hello! I am Point!/n"); } }; /** *Line */ class CLine : public CShape { public: CLine(){} ~CLine(){} void Draw() { printf("Hello! I am Line!/n"); } }; void main() { CShape* shape = new CPoint(); //draw point shape->Draw();//调用CShape的Draw()函数 delete shape; shape = new CLine(); //draw Line shape->Draw();//调用CShape的Draw()函数 delete shape; return ; }

如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。

下面这个例子就是静态多态,在编译阶段就知道要调用的函数:

 

template <class T> 
void DrawShape(T* t) 
{ 
t->Draw(); 
} 
  
修改main函数为如下: 
  
void main() 
{ 
CShape* shape = new CPoint(); 
//draw point 
shape->Draw(); 
  
DrawShape<CPoint>((CPoint*)shape); 
delete shape; 
  
shape = new CLine(); 
//draw Line 
shape->Draw(); 
DrawShape<CLine>((CLine*)shape); 
delete shape; 
  
  
return ; 
}

对于Java的程序员,也可以实现多态,但是只要子类继承了父类,并且在子类中重写了父类中的同名方法,那么将子类作为父类的变量值的时候,运行的时候会调用子类的方法而不是父类的,为什么会出现这种情况?如果按照C++的这种写法,那么只要不是虚函数,就调用的一定是父类的,答案在于Java中的函数都是虚函数。

原文地址:https://www.cnblogs.com/zuiyirenjian/p/3163534.html