摘要:多态性提供一组统一的调用接口函数,依据这些条用接口函数具体对象的不同,同一名字的函数会有不同的行为。

1、重载与隐藏

(1)、对同一作用域中的同名函数,如果它们的函数特征标不同,那么它们就形成一种重载关系。

(2)、基类与派生类中非虚同名函数,不管它们的参数特征标是否相同,它们都形成隐藏关系,即派生类对象隐藏基类中的同名函数。

 #include <iostream>

 using namespace std;

 class Animal
{
public:
void walk()
{
cout << "Animal walk.\n";
}
void walk(int walkWay)
{
switch(walkWay)
{
case :
cout << "Animal jump...\n";
break;
case :
cout << "Animal fly...\n";
break;
default:
cout << "Animal scrawling...\n";
}
}
void sleep()
{
cout << "Animal sleeping..." << endl;
}
};
class Human:public Animal
{
public:
void sleep()
{
cout << "Human sleep, lying...\n";
}
}; int main()
{
Animal *pAnimal = NULL;
Animal animal;
Human human; pAnimal = &animal;
pAnimal->sleep(); pAnimal = &human;
pAnimal->sleep(); Human *pHuman = &human;
pHuman->sleep(); pHuman->walk();
pHuman->walk(); int c;
cin >> c;
return ;
}

(3)、在此示例代码中,同一类中的成员函数walk()与walk(int walkWay)形成重载。

(4)、分别位于基类Animal与派生类Human中的成员函数sleep()形成隐藏关系,即派生类Human的sleep()隐藏了基类的Animal中成员函数sleep()。

(5)、依据基类和派生类的兼容性原则,可以将派生类Human对象human的地址赋值给基类Animal的指针pAnimal。不过这时pAnimal指向的函数永远是基类的成员函数。

(6)、由于派生类Human的sleep()隐藏了基类Animal中的成员函数sleep(),所以pHuman->sleep()调用派生类Human的sleep()。

(7)、注意:基类指针永远无法调用该基类派生的同名函数。

2、多态性

(1)、虚函数:若类的成员函数用关键字virtual修饰,则称该函数为该类的虚函数,其声明语法如下:

virtual 返回值类型 函数名(形参列表);

例如:

class Animal

{

public:

  virtual void sleep()

  {

    cout << "Animal sleep." << endl;

  }

};

(2)、函数覆盖:若位于基类和派生类中的两个同名虚函数的声明完全相同(包括返回值类型),则这样的两个函数形成覆盖关系。

例如:

class Pet

{

  virtual void sleep()

  {

    cout << "Pet sleep." << endl;

  }

};

class Fish:public Pet

{

  virtual viod sleep()

  {  

    cout << "Fish sleep." << endl;

  }

};

(3)、多态性实现步骤:

1)、在基类中说明成员函数为virtual函数,在直接派生类或间接派生类中根据实际应用重写这些virtual函数。

2)、在直接派生类或间接派生类中覆盖那些virtual函数,它们的声明必须和基类对应的虚函数声明严格一致。

3)、声明基类指针或者基类引用;给基类指针或者引用赋值,此时对象地址既可以是基类对象地址,也可以是派生类对象地址;有指针或者引用去调用相应的virtual函数,

根据对象的不同,真正被调用的函数可以是基类同名函数,也可以是派生类同名函数。

 #include <iostream>

 using namespace std;

 class Animal
{
public:
virtual void walk()
{
cout << "Animal walk." << endl;
}
void walk(int walkWay)
{
switch(walkWay)
{
case :
cout << "Animal jump..." << endl;
break;
case :
cout << "Animal fly..." << endl;
break;
default:
cout << "Animal scraling..." << endl;
}
}
virtual void sleep()
{
cout << "Animal sleeping..." << endl;
}
private:
}; class Human:public Animal
{
public:
virtual void walk()
{
cout << "Human walk by feet." << endl;
}
virtual void sleep()
{
cout << "Human sleep, lying..." << endl;
}
virtual void talk()
{
cout << "Human talking..." << endl;
}
private:
};
int main()
{
Animal *pAnimalArray[] = {
new Animal, new Human
};
for(int i = ;i < ;i++)
{
pAnimalArray[i]->walk();
pAnimalArray[i]->sleep();
delete pAnimalArray[i];
}
int c;
cin >> c;
return ;
}

(4)、注意:若在类中只声明虚函数原型,则在类外部定义虚函数时不必加virtual关键字;若派生类覆盖基类某个虚函数,则派生类中对应的虚函数可以加virtual也可以

加;一个虚函数,他在直接派生类和间接派生类中依然保持虚函数的特性;虚函数必须是成员函数;只有通过指针或引用方式访问虚函数,才能获得虚函数的动态特性。

3、virtual析构函数

(1)、通常,我们会才用基类指针或引用来指向派生类对象,此时,使用delete释放堆中的对象时,只会释放其基类子对象部分而不会自动释放派生类子对象部分。解决

办法是把基类和派生类的析构函数都声明为virtual类型。

 #include <iostream>

 using namespace std;

 class Vehicle
{
public:
Vehicle(int power)
{
this->power = power;
}
virtual ~Vehicle()
{
cout << "deleting Vehicle sub object..." << endl;
}
public:
virtual void run()
{
cout << "Vehicle running..." << endl;
}
private:
int power;
};
class Plane:public Vehicle
{
public:
Plane(int power, double height):Vehicle(power)
{
this->height = height;
}
virtual ~Plane()
{
cout << "deleting Plane sub object..." << endl;
}
public:
void run()
{
cout << "Plane fly..." << endl;
}
private:
double height;
};
int main()
{
{
Vehicle *pVehicle = new Plane(, );
delete pVehicle;
}
int c;
cin >> c;
return ;
}

4、纯虚函数和抽象类

(1)、纯虚函数:类中的virtual成员函数,如果没有实现体(即定义实现体为0),则称这样的函数为纯虚函数。

例如:

virtual void add()=0;

(2)、抽象类:当一个类含有一个或者多个纯虚函数时,称这样的类为抽象类。

注意:抽象类的纯虚函数可以是我们后续加入的或者从基类继承的,当然如果一个类继承一个或多个纯虚函数之后再一一实现这些纯虚函数,那么这样的类不再是抽象类;

抽象类不能用于创建对象,但允许定义抽象对象指针。

 #include <iostream>

 using namespace std;

 const double PI = 3.14159;

 class Shape
{
public:
virtual void show() = ;
virtual double area() = ;
virtual ~Shape()
{}
};
class Shape2D:public Shape
{
public:
Shape2D(double x, double y)
{
this->x = x;
this->y = y;
}
protected:
double x;
double y;
};
class Shape3D:public Shape
{
public: protected:
double x;
double y;
double z;
};
class Circle:public Shape2D
{
public:
Circle(double x, double y, double radius):Shape2D(x, y)
{
this->radius = radius;
}
virtual void show()
{
cout << "Circle center: (" << x << ", " << y << ")" << endl;
}
virtual double area()
{
return PI*radius*radius;
}
private:
double radius;
};
class Sphere:public Shape3D
{
public:
Sphere(double x, double y, double z, double radius)
{
this->x = x;
this->y = y;
this->z = z;
this->radius = radius;
}
void show()
{
cout << "Sphere center:(" << x << ", " << y << ", " << z << ")" << endl;
}
double area()
{
return PI*radius*radius*radius;
}
private:
double radius;
};
int main()
{
{
Shape *pShape = NULL;
Shape *pShapeArray[] = {
new Circle(1.0, 2.0, 3.0),
new Sphere(1.0, 2.0, 3.0, 4.0)
};
for(int i = ;i < ;i++)
{
pShapeArray[i]->show();
cout << "\t area = " << pShapeArray[i]->area() << endl;
delete pShapeArray[i];
}
}
int c;
cin >> c;
return ;
}

C++面向对象程序设计的一些知识点(3)的更多相关文章

  1. C++面向对象程序设计的一些知识点(5)

    摘要:运算符能给程序员提供一种书写数学公式的感觉,本质上运算符也是一种函数,因此有类内部运算符和全局运算符之分,通过重载,运算符的“动作”更加有针对性,编写代码更像写英文文章. 1.C++标准允许将运 ...

  2. C++面向对象程序设计的一些知识点(4)

    摘要:累继承可以实现源代码重用,模板技术也可以达到同样的目的.模板可以分为函数模板和类模板,其共同点是允许参数类进行类型化,编译器根据程序员传递的具体类型,又把函数模板实例化为具体函数,把类模板实例化 ...

  3. C++面向对象程序设计的一些知识点(2)

    1.C++中三种继承方式及派生类中访问控制规则 (1).C++支持的三种继承方式是public.protected.private.C++允许一个类同时以不同的方式对不同的基类加以继承. (2). 不 ...

  4. C++面向对象程序设计的一些知识点(1)

    1.函数重载而不出错是有条件的: (1).这些函数位于同一域内,如同一类中.同一文件中. (2).这些同名函数具有不同的参数特征标(特征标是指形參的个数.类型.排列顺序等). 2.引用特性(与指针对比 ...

  5. 对面向对象程序设计(OOP)的认识

    前言 本文主要介绍面向对象(OO)程序设计,以维基百科的解释: 面向对象程序设计(英语:Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发 ...

  6. 20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计

    20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 ...

  7. 2018-2019-2 20175217 实验二《Java面向对象程序设计》实验报告

    一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:吴一凡 学号:20175217 指导教师:娄嘉鹏 实验日期:2019年4月15日 实验时间:--- 实验序号:实验二 实验名称:Jav ...

  8. 20175315 实验二《Java面向对象程序设计》实验报告

    20175315 实验二<Java面向对象程序设计>实验报告 一.实验内容及步骤 1.初步掌握单元测试和TDD 单元测试 任务一:三种代码 用程序解决问题时,要学会写以下三种代码: 伪代码 ...

  9. 2018-2019-2 20175202实验二《Java面向对象程序设计》实验报告

    2018-2019-2 20175202实验二<Java面向对象程序设计>实验报告 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初 ...

随机推荐

  1. java如何将毫秒数转为相应的年月日格式

    public static void main(String[] args) { Date date = new Date(); Long time = date.getTime(); System. ...

  2. 通过修改css文件来观察openerp表单中的col和colspan

    适用版本 openerp 6.1.1 问题的提出 在openerp的表单定义中, 要使用 colspan和col 指你定各个元素的占位, 前者说明了本元素占据其所在容器的列数, 后者说明了本元素作为容 ...

  3. oracle 建表时显示ORA-00984: 列在此处不允许

      oracle 建表时显示ORA-00984: 列在此处不允许 CreationTime--2018年7月19日16点10分 Author:Marydon 1.情景展示 使用plsql建表时,报错 ...

  4. 导出CCS3.3数据及使用matlab处理的方法

    CCS3.3是一款DSP的集成开发环境(IDE).在做DSP开发时,为验证算法.经常须要使用matlab进行算法验证,验证算法就须要数据.因此,一种交互的方法是: 使用DSP开发板连接CCS 用CCS ...

  5. Linux终端监控工具之dstat

    1.安装 yum install dstat 2.示例 1)直接跟数字,表示#秒收集一次数据,默认为一秒:dstat 5表示5秒更新一次 这是默认输出显示的信息: CPU状态:CPU的使用率.这项报告 ...

  6. spring注解 di 和 ioc 注解

    注解: 1.注解就是为了说明java中的某一个部分的作用(Type) 2.注解都可以用于哪个部门是@Target注解起的作用 3.注解可以标注在ElementType枚举类所指定的位置上 4. @Do ...

  7. iOS同一项目多个Target的快速实现方法 - 两种使用场景详解

    我们项目中,默认建好是只有一个target的,但是,一些场景中,多target能帮助我们更好的使用项目. 场景1: 同一项目,一般会分不同环境:开发环境.测试环境.正式(生产)环境. 这就涉及到一个请 ...

  8. HDUOJ----4501小明系列故事——买年货(三维背包)

    小明系列故事——买年货 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  9. 从一个activity返回

    页面之间的跳转有startActivity 和startActivityForResult两种, 返回的话用finish方法,如下示例 MyActivity.this.finish();那你返回按钮使 ...

  10. FA_固定资产六大业务增加、修改、报废、在建、折旧、盘点概述(概念)

    2014-06-04 Created By BaoXinjian