C++面向对象程序设计的一些知识点(3)
摘要:多态性提供一组统一的调用接口函数,依据这些条用接口函数具体对象的不同,同一名字的函数会有不同的行为。
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)的更多相关文章
- C++面向对象程序设计的一些知识点(5)
摘要:运算符能给程序员提供一种书写数学公式的感觉,本质上运算符也是一种函数,因此有类内部运算符和全局运算符之分,通过重载,运算符的“动作”更加有针对性,编写代码更像写英文文章. 1.C++标准允许将运 ...
- C++面向对象程序设计的一些知识点(4)
摘要:累继承可以实现源代码重用,模板技术也可以达到同样的目的.模板可以分为函数模板和类模板,其共同点是允许参数类进行类型化,编译器根据程序员传递的具体类型,又把函数模板实例化为具体函数,把类模板实例化 ...
- C++面向对象程序设计的一些知识点(2)
1.C++中三种继承方式及派生类中访问控制规则 (1).C++支持的三种继承方式是public.protected.private.C++允许一个类同时以不同的方式对不同的基类加以继承. (2). 不 ...
- C++面向对象程序设计的一些知识点(1)
1.函数重载而不出错是有条件的: (1).这些函数位于同一域内,如同一类中.同一文件中. (2).这些同名函数具有不同的参数特征标(特征标是指形參的个数.类型.排列顺序等). 2.引用特性(与指针对比 ...
- 对面向对象程序设计(OOP)的认识
前言 本文主要介绍面向对象(OO)程序设计,以维基百科的解释: 面向对象程序设计(英语:Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发 ...
- 20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计
20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 ...
- 2018-2019-2 20175217 实验二《Java面向对象程序设计》实验报告
一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:吴一凡 学号:20175217 指导教师:娄嘉鹏 实验日期:2019年4月15日 实验时间:--- 实验序号:实验二 实验名称:Jav ...
- 20175315 实验二《Java面向对象程序设计》实验报告
20175315 实验二<Java面向对象程序设计>实验报告 一.实验内容及步骤 1.初步掌握单元测试和TDD 单元测试 任务一:三种代码 用程序解决问题时,要学会写以下三种代码: 伪代码 ...
- 2018-2019-2 20175202实验二《Java面向对象程序设计》实验报告
2018-2019-2 20175202实验二<Java面向对象程序设计>实验报告 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初 ...
随机推荐
- 用css3做一个求婚小动画
概述 本案例主要是运用到了css3的animation.keyframes.transform等属性,熟悉了,就可以做更多的其他动画效果,这几个属性功能非常强大. 详细 代码下载:http://www ...
- 不止是动态化:Weex项目和阿里无线技术开源方向
这是开发者正在书写的峥嵘岁月.受益开源,回馈社区.阿里巴巴集团已经开源115个项目,并正式加入FSF基金会,Apache基金会,linux 基金会和Xen的顾问团队,并在云栖大会北京峰会宣布AliSQ ...
- Android 5.0 + IDA 6.8 调试经验分享
如今升级快.网上的资料仅仅能做參考. 学到了NDK逆向这一块,昨天为了能让IDA 能动态调试SO,瞎折腾了非常久,这里分享一下我的经验. 工具: IDA pro 6.8 Android 5.x IDA ...
- PHP-多域名单点登陆方案
1.只是二级域名不同(比如a.xx.com, b.xx.com) 利用cookie, 设置domain为".xx.com"即可 2.多个本域名都不相同(比如www.a.com, w ...
- write()和prinln()的区别?
输出数字不同: write()输出数字转换为字符,println原样输出. 输出null不同: write()输出引用类型的时候调用的toString转换为String数据,因此如果对象为null那么 ...
- iOS GCD中级篇 - dispatch_group的理解及使用
上一篇GCD基础篇,以及同步.异步,并发.并行几个概率的理解 关于dispatch_group的概念以及几种场景下的使用 1.关于dispatch_group 把一组任务提交到队列中,这些队列可以不相 ...
- HDUOJ-----Difference Between Primes
Difference Between Primes Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- HDUOJ-----X问题
X问题 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- Microsoft Office2003打开office2007文件的补丁
Microsoft office2003打开office2007,不需要安装2007,只需要装一个补丁即可 搜索:office2003打开office2007文件的补丁
- asp.net core mvc视频A:笔记3-7.ViewStart与ViewImort
项目位置 放在其它目录应该不会执行! 默认配置 默认配置