C++--第17课 - 继承与多态 - 上

第17课 - 继承与多态 - 上

引入:

如果子类定义了与父类中原型相同的函数会发生什么?

1. 函数重写

在子类中定义与父类中原型相同的函数,函数重写只发生在父类与子类之间。

父类中被重写的函数依然会继承给子类,默认情况下子类中重写的函数将隐藏父类中的函数,通过作用域分辨符::可以访问到父类中被隐藏的函数。

#include <cstdlib>

#include <iostream>

using namespace std;

class Parent

{

public:

void print()

{

cout<<"I‘m Parent..."<<endl;

}

};

class Child : public Parent

{

public:

void print()

{

cout<<"I‘m Child..."<<endl;

}

};

int main(int argc, char *argv[])

{

Child child;

child.print();

child.Parent::print();

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

I‘m Child...

I‘m Parent...

当函数遇到兼容性问题的时候:

#include <cstdlib>

#include <iostream>

using namespace std;

class Parent

{

public:

void print()

{

cout<<"I‘m Parent..."<<endl;

}

};

class Child : public Parent

{

public:

void print()

{

cout<<"I‘m Child..."<<endl;

}

};

void howToPrint(Parent* p)

{

p->print();

}

void run()

{

Child child;

Parent* pp = &child;   //赋值兼容性原则,当使用父类的时候都能用子类来代替。

Parent& rp = child; //Parent类引用,应用Child类对象

child.print();

pp->print();  //指针打印

rp.print();   //引用的打印

}

int main(int argc, char *argv[])

{

run();

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

I‘m Child...

I‘m Parent...

I‘m Parent...

分析:

pp执行child,rp引用child。但是后面的两条语句都没有打印I‘m Child...,而是I‘m Parent...。

l  问题所在:

(1)      C++与C相同,是静态编译型语言。

(2)      在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象。

(3)      所以编译器认为父类指针指向的是父类对象(根据赋值兼容性原则,这个假设合理)。

(4)      由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象。

(5)      从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数。

对于下面的程序:

void howToPrint(Parent* p)

{

p->print();

}

在编译这个函数的时候,编译器不可能知道指针 p 究竟指向了什么。但是编译器没有理由报错。于是,编译器认为最安全的做法是编译到父类的print函数,因为父类和子类肯定都有相同的print函数。

2. 程序—函数重写实例(江湖恩怨)

#include <cstdlib>

#include <iostream>

using namespace std;

/*大boss挑战庄主与少庄主*/

class Boss   //大boss

{

private:

static Boss* cInstance;  //单例模式,就一个 .声明

Boss()

{

}

public:

static Boss* GetInstance()

{

if( cInstance == NULL )

{

cInstance = new Boss();

}

return cInstance;

}

int fight()

{

cout<<"Boss::fight()"<<endl;   //大boss出招

return 10;

}

};

Boss* Boss::cInstance = NULL;

//静态变量上面是声明,下面是定义,否则没有意思。

class Master   //庄主

{

public:

virtual int eightSwordKill() //八剑齐飞

{

cout<<"Master::eightSwordKill()"<<endl;

return 8;

}

};

class NewMaster : public Master //少庄主

{

public:

virtual int eightSwordKill()

{

cout<<"NewMaster::eightSwordKill()"<<endl;

return Master::eightSwordKill() * 2;

}

};

void fieldPK(Master* master, Boss* boss)

{

int k = master->eightSwordKill();

int b = boss->fight();

if( k < b )

{

cout<<"Master is killed..."<<endl;

}

else

{

cout<<"Boss is killed..."<<endl;

}

}

int main(int argc, char *argv[])

{

Boss* boss = Boss::GetInstance();

cout<<"Master vs Boss"<<endl;

Master master;

fieldPK(&master, boss);

cout<<"New Master vs Boss"<<endl;

NewMaster newMaster;

fieldPK(&newMaster, boss);

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Master vs Boss

Master::eightSwordKill()

Boss::fight()

Master is killed...

New Master vs Boss

NewMaster::eightSwordKill()

Master::eightSwordKill()

Boss::fight()

Boss is killed...

3. 多态的本质

l  面向对象的新需求

根据实际的对象类型来判断重写函数的调用。

如果父类指针指向的是父类对象则调用父类中定义的函数。

如果父类指针指向的是子类对象则调用子类中定义的重写函数。

l  面向对象中的多态

根据实际的对象类型决定函数调用语句的具体调用目标。

多态:同样的调用语句有多种不同的表现形态

l  C++中的多态支持

C++中通过virtual关键字对多态进行支持。

使用virtual声明的函数被重写后即可展现多态特性。

这就是虚函数。虚函数的特点是,不再只是根据指针类型来判定要使用的函数,而是根据指针所指的内容来判断将要引用的函数。

小结

函数重写是面向对象中很可能发生的情形。

函数重写只可能发生在父类与子类之间。

需要根据实际对象的类型确定调用的具体函数。

virtual关键字是C++中支持多态的唯一方式。

被重写的虚函数即可表现出多态的特性。

原文地址:https://www.cnblogs.com/free-1122/p/11336223.html

时间: 2024-10-12 13:16:09

C++--第17课 - 继承与多态 - 上的相关文章

Java学习笔记--继承和多态(上)

1.通过继承来开发超类(superclass) 2.使用super 关键词唤起超类的构造方法 3.在超类中覆盖方法 4.区分override和overload 5.在Object类中探索toString()类 6.发现多态性和动态绑定 7.描述解释为什么向下转型是必须的 8.在Object类中探索equals 方法 9.存储,取回,实现ArrayLis的对象 10.使用ArrayList类实现Stack 11.超类中使用数据和方法,protected 12.使用final模块来禁止类和方法的覆盖

2、C#面向对象:封装、继承、多态、String、集合、文件(上)

面向对象封装 一.面向对象概念 面向过程:面向的是完成一件事情的过程,强调的是完成这件事情的动作. 面向对象:找个对象帮你完成这件事情. 二.面向对象封装 把方法进行封装,隐藏实现细节,外部直接调用. 打包,便于管理,为了解决大型项目的维护与管理. 三.什么是类? 将相同的属性和相同方法的对象进行封装,抽象出 “类”,用来确定对象具有的属性和方法. 类.对象关系:人是类,张三是人类的对象. 类是抽象的,对象是具体的.对象可以叫做类的实例,类是不站内存的,对象才占内存. 字段是类的状态,方法是类执

C++里的继承和多态(上)

  继承 1.私有继承:基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问. 公有继承:基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的访问权限,而基类的私有成员在派生类中是不可见的. 在公有继承时,派生类的成员函数可以访问基类中的公有成员和保护成员:派生类的对象仅可以访问基类中的公有成员. 保护继承:基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数访问,不能被它派生类的对象访问. 2.注意: 1>基类的private成员

第三课 Delphi中的封装,继承,多态的应该实例运用

   上一讲我们提到什么是封装,继承.和多态,现在我们讲解delphi中是如何实现它们的?以及为什么我们需要封装,继承和多态. 1.首先来说封装,delphi中用关键字private修饰符来说明,即表示类的成员为私有的,在类的外部是不可见了,只有在本类中可以随便使用.它的访问权限最低. 2.delphi中还有一个比较特殊的修饰符protected,表示该类的成员为保护型.受保护的成员只能由该类的和派生类可以访问.如果想要子类继承父类的某些功能的时候,可以使用某些成员为protected类型,访问

黑马程序员 面向对象(上) 封住,继承,多态,以及this和super的用法

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ----------------------/* * 一.类的继承: 当多个类出现了相同的属性和行为时,我们可以把这些类中相同的属性和行为抽取出来 成为独立的一个类,然后让这些类分别去继承抽取类,再根据自己需求去实现别的功能 这样大大的增强的相同代码的复用性,也使代码变得美观 我们把这个抽取类叫做这些类的父类,这些类叫做抽取类的子类,子类是可以继承父类中 的所有信息. 在Java中所有的类

JAVA基础——面向对象三大特性:封装、继承、多态

JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据.     隐藏类的实例细节,方便修改和实现. 3.封装的实现步骤 需要注意:对封装的属性不一定要通过get/set方法,其他方法也可以对封装的属性进行操作.当然最好使用get/set方法,比较标准. A.访问修饰符 从表格可以看出从上到下封装性越来越差. B.this关键字 1.this关键字代表当前

[转]Java中继承、多态、重载和重写介绍

什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承.多态.重载和重写. 继承(inheritance) 简单的说,继承就是在一个现有类型的基础上,通过增加新的方法或者重定义已有方法(下面会讲到,这种方式叫重写)的方式,产生一个新的类型.继承是面向对象的三个基本特征--封装.继承.多态的其中之一,我们在使用JAVA时编写的每一个类都是在继承,因为在JAVA语言中,java.lang.Object类是所有类最根本的基类(或者叫父类.超类),如果

网络电视精灵~分析~~~~~~简单工厂模式,继承和多态,解析XML文档

小总结: 所用技术: 01.C/S架构,数据存储在XML文件中 02.简单工厂模式 03.继承和多态 04.解析XML文档技术 05.深入剖析内存中数据的走向 06.TreeView控件的使用 核心:通过该项目,我们对业务流程有一个整体把控.对继承和多态有深入的了解 下面是类图: 主界面图: 核心思路: 1   1.首先在频道管理类ChannelManager中写一个加载所有频道方法LoadAllChannel; 2   3        该方法作用读取FullChannels.xml文件,并且

转 OC温故:类的三大特性(封装,继承,多态)

原文标题:OC学习篇之---类的三大特性(封装,继承,多态) 我们都知道,面向对象程序设计中的类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今天就来看一下OC中类的三大特性: 一.封装 封装就是对类中的一些字段,方法进行保护,不被外界所访问到,有一种权限的控制功能,Java中有四种访问权限修饰符: 1 public,default,protected,private 访问权限依次递减,这样我们在定义类的时候,哪些字段和方法不想暴露出去,哪些字段和方法可以暴露,可以通过