前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++基础(七).多态(2)

C++基础(七).多态(2)

作者头像
franket
发布2021-09-15 19:52:12
4150
发布2021-09-15 19:52:12
举报
文章被收录于专栏:技术杂记

代码示例

shape.cpp

代码语言:javascript
复制
#include <iostream> //cout,endl 相关函数的声明

#define PI 3.1415926 //定义一个PI宏

using namespace std; //设定名称空间

class Shape //定义一个Shape的抽象基类
{
public:
  virtual float getArea()=0; //声明一个纯虚函数
  Shape(float x=0); //声明一个带默认参值的构造函数
protected:
  float h; //成员变量
};

Shape::Shape(float x) //构造函数的实现
{
  h=x;
}

class Circle:public Shape //定义一个继成自Shape抽象类的派生类Circle
{
public:
  Circle(float r=0); //构造方法
  float getArea(); //对getArea的重写
};

Circle::Circle(float r):Shape(r) //构造函数的实现,因为圆只有一个表示半径的成员变量,所以使用基类的构造方法进行初始化就够了
{}

float Circle::getArea() //对getArea的实现
{
  return PI*h*h;
}


class Rectangle:public Shape //定义一个继成自Shape抽象类的派生类Rectangle
{
public:
  Rectangle(float h=0,float x=0); //声明构造方法
  float getArea(); //对getArea的重写
protected:
  float w; //多了一个表示宽度的成员变量
};

Rectangle::Rectangle(float h,float x):Shape(h) //构造函数的实现,因为矩形多了一个表示宽度的成员变量,所以使用基类的构造方法进行初始化后,再只用对宽度单独赋值就可以了
{
  w=x;
}

float Rectangle::getArea() //对getArea的实现
{
  return h*w;
}

class Trapezoid:public Shape  //定义一个继成自Shape抽象类的派生类Trapezoid
{
public:
  Trapezoid(float h=0,float x=0,float y=0); //声明构造方法
  float getArea(); //对getArea的重写
protected:
  float a,b; //多了两个分别表示上底和下底的成员变量
};

Trapezoid::Trapezoid(float h , float x, float y):Shape(h)  //构造函数的实现,因为梯形多了两个分别表示上下底的成员变量,所以使用基类的构造方法进行初始化后,再只用对两底赋值就可以了
{
  a=x;
  b=y;
}

float Trapezoid::getArea() //对getArea的重写
{
  return h*(a+b)/2;
}

int main()
{
  Shape *p[3]={NULL,NULL,NULL}; //定义三个基类(抽象类)指针

  p[0] = new Circle(2); //申请一个Circle类对象,初始化半径为2,指针赋给p[0]
  p[1] = new Rectangle(2,5); //申请一个Rectangle类对象,初始化高为2,宽为5,指针赋给p[1]
  p[2] = new Trapezoid(2,5,8); //申请一个Trapezoid类对象,初始化高为2,上底为5,下底为8,指针赋给p[2]

  cout<<"Circle area:"<<p[0]->getArea()<<endl;
  cout<<"Rectangle area:"<<p[1]->getArea()<<endl;
  cout<<"Trapezoid area:"<<p[2]->getArea()<<endl;
  cout<<"the total area:"<<p[0]->getArea()+p[1]->getArea()+p[2]->getArea() <<endl;
  
  delete p[0];
  delete p[1];
  delete p[2]; //进行清场工作
  
  return 0;
}

编译执行

代码语言:javascript
复制
emacs@ubuntu:~/c++$ alias  gtx
alias gtx='g++ -Wall -g -o'
emacs@ubuntu:~/c++$ gtx shape.x shape.cpp
emacs@ubuntu:~/c++$ ./shape.x 
Circle area:12.5664
Rectangle area:10
Trapezoid area:13
the total area:35.5664
emacs@ubuntu:~/c++$

编译执行过程中没有报错,从结果来看,符合预期


总结

弄清下面概念对掌握c++很有帮助

  • 多态:指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作,C++支持两种多态性:编译时多态性,运行时多态性(编译时多态性:通过重载函数实现 ;运行时多态性:通过虚函数实现)
  • 虚函数 :在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override)
  • 纯虚函数:纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
  • 抽象类:包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象
  • 接口:接口只是一个概念,它在C++中用抽象类来实现,只包含纯虚函数的抽闲类叫接口
  • 虚基类:虚基类是相对于它的派生类而言的(虚基类只是一种特殊关系),它本身可以是一个普通的类
  • 一个抽象类只能用作基类,只能用作派生,不能实例化(创建)对象。一个类要是包含至少一个纯虚函数,则这个类是抽象类。一个抽象类的子类可以添加更多的数据成员和成员函数
  • 抽象类的子类可以还是抽象类,可以添加更多的成员函数和成员方法,直到可以产生对象为止
  • 由于抽象类不能构造对象,因此它的构造函数不能被单独调用。它的构造函数只能在子类的成员初始化列表里面调用
  • 抽象类不一定有析构函数,如果有必须是虚析构函数
  • 一个函数不能有抽象类对象的值参数<参数不能传值>,这个函数不能有抽象类对象的值返回。然而可以有抽象类类型的指针和引用可以作为参数,同样抽象类的指针和引用可以作为函数的返回值类型。因为他们可以指向或者引用抽象类的子类对象
  • 纯虚函数是在子类里面被实现的。如果子类没有实现纯虚函数,纯虚函数将继承给子类。那么这时子类同样也是一个抽象类

原文地址

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代码示例
  • 编译执行
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档