C++的一些基本特性(4)——面向对象之 重载与多态

零、引言
重载与多态,OOP的又两大特性。在笔者看来,它们在功能意义上存在着一定的共性——通过重载和多态,将方法的调用简化(比如你想实现数字的加法1+1,又想实现汽车的加法car+car,严格来说二者并不相通,但人类的认识将其中加法的共性提取出来,而计算机则通过重载实现),实现方法的通用性。 这二者也存在着一定的区别,我们先分别讨论它们各自的内容,最后再进行区别的总结。

一、重载
在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载运算符重载。当调用重载函数或者运算符的时候,面对多个定义,编译器就需要进行判断,选择合适的定义进行操作,这一过程则称为重载决策,判断的依据则是根据使用的参数类型。

函数重载:

在同一个作用范围,定义多个功能类似的同名函数,但函数的形式参数(包括参数的个数、类型)必须不同,从而来实现函数的重载。这里,就体现了重载决策是根据参数类型进行判断的。

一个printf()函数重载的例子如下:

#include <iostream>
using namespace std;
 
class printData
{
   public:
   		
   		//同名函数,形参差异,函数重载
      void print(int i) {
        cout << "整数为: " << i << endl;
      }
 
      void print(double  f) {
        cout << "浮点数为: " << f << endl;
      }
 
      void print(char c[]) {
        cout << "字符串为: " << c << endl;
      }
};
 
int main(void)
{
   printData pd;
 
   // 输出整数
   pd.print(5);
   // 输出浮点数
   pd.print(500.263);
   // 输出字符串
   char c[] = "Hello C++";
   pd.print(c);
 
   return 0;
}

运算符重载:

运算符就是我们常用的+.-,*,/(加减乘除)等符号,它们可以看成特殊的函数。实现运算符的重载的方式有二:

定义为类成员函数,则只需要一个参数:

return_tyep operator重载符号(type_name parameter)
//例子如下
Box operator+(const Box&);

定义为普通的函数(非成员函数),则需要两个参数:

return_tyep operator重载符号(type_name parameter1,type_name parameter2)
Box operator+(const Box&, const Box&);

+运算符的重载示例如下,其实现了Box类型的加法:

#include <iostream>
using namespace std;
 
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 Box 对象相加
      Box operator+(const Box& b)
      {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box
   Box Box2;                // 声明 Box2,类型为 Box
   Box Box3;                // 声明 Box3,类型为 Box
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把两个对象相加,得到 Box3
   Box3 = Box1 + Box2;
 
   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}

二、多态
“当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态”。通俗来说,就是对于基类和派生类,在调用成员函数时,会根据对象的特点(不同的派生类),产生不同的响应。(还是拿动物的例子来说,就好像胎生动物和卵生动物,生殖()是动物的一个方法,但是对于胎生动物和卵生动物,它们的实现方式是不同的)

多态是通过虚函数实现的,虚函数是在基类中使用关键字 virtual 声明的函数。对于每个子类,都有一个同名的函数来独立实现,这种称为动态多态,或动态链接。
基类中,虚函数可以没有内容,则称为纯虚函数,其为虚函数的一个特例,=0用来告诉编译器该虚函数为纯虚函数。

如果未指定virtual虚函数,子类的被调用函数为基类的版本,则称为静态多态,或静态链接。

一个虚函数、纯虚函数以及静态多态的例子如下:

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      /*----------------虚函数----------------------*/
      
       virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
       /*-------------------------------------------*/
       
       /*----------------纯虚函数----------------------*/
      /*
       virtual int area()=0;
      */
      /*----------------------------------------------*/
      
        /*----------------静态多态----------------------*/
      /*
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
      */
      /*----------------------------------------------*/
  	 

};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
 
   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}

三、重载与多态的关系
前面提到,重载和多态存在一定的共性,它们间的区别主要有:

  • 重载:函数名相同,形参不同,根据参数和形参选择合适的实现函数(通常是同一类内 )
  • 多态:函数名相同,形参相同,根据调用的对象所属的类选择对应的函数(不同的派生类间)

四、结语
C++的面向对象基本特性就介绍到此,其余内容笔者计划在实践中去了解和认识。等忙完有关任务后,后期还会进一步精炼对C++的理解。

以上内容来自笔者根据菜鸟教程的总结和归纳,并添加一些内容和注释

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值