多态性与虚函数
多态性(函数重载,运算符重载就是多态性现象)
多态性 :向不同对象发送同一个消息,不同对象在接收时会产生不同的行为。(每个对象用自己的方式去响应共同的消息)
多态性又可以分为静态多态性和动态多态性
静态多态性在编译时编译系统就可以判定调用哪个重载运算符(函数)。

#include<iostream>
using namespace std;
class point {
public:
point(float a, float b) { //构造函数
x = a; y = b;
}
friend ostream & operator <<(ostream &, point &); //运算符重载
protected:
float x, y;
};
std::ostream &operator<<(std::ostream &output, point &p) { //运算符重载的定义
output << "(" << p.x << "," << p.y << ")" << endl;
return output;
}
class circle :public point {
public:
circle(float a, float b, float c) :point(a, b), radius(c) {} //构造函数
friend ostream &operator <<(ostream &, circle &); protected:
float radius;
};
ostream &operator <<(ostream &output, circle &c) {
output << "(" << c.x << "," << c.y << ")," << "radius=" << c.radius << endl;
return output;
}
int main() {
point a(2.3, 4.6);
cout << "the point is:" << a << endl;
circle m(, , );
cout << "the circle is" << m << endl;
}
利用虚函数实现动态多态性
(所谓虚函数,就是在基类声明函数是虚拟的,并不是实际存在的函数,
  然后在派生类中才正式定义此函数,在程序运行期间,用指针指向某一派生类的对象,这样就能调用指针指向的派生类对象的函数)

#include<iostream>
using namespace std;
class point {
public:
point(float a, float b) { //构造函数
x = a; y = b;
}
virtual void display(); //虚函数
protected:
float x, y;
};
void point::display(){
cout<<"(" << x << "," << y << ")"<<endl;
} class circle :public point {
public:
circle(float a, float b, float c) :point(a, b), radius(c) {} //构造函数
void display();
protected:
float radius;
};
void circle::display(){
cout<< "(" << x << "," << y << ")," << "radius=" << radius << endl;
}
int main() {
point a(2.3, 4.6);
circle m(, , );
point *p1=&a; //基类指针
p1=&m;
p1->display();
return ;
}
输出的结果是:(0,0)radius=8
说明:本来基类指针是用来指向基类对象的,如果把它指向派生类对象,则自动进行指针类型转换,
将派生类的对象的指针先转换为基类指针,这样基类指针指向的就是对象中的基类成分。
虚函数突破了这一限制,基类的display函数声明为虚函数,在声明派生类时被重载,这时派生类的同名函数display就取代了基类的虚函数。
虚函数的使用方法:
1.在基类声明成员函数为虚函数,在类外定义虚函数是不必加virtual
2.一个成员函数被声明为虚函数后,在同一类族中的类就不能在定义一个非virtual的但与该虚函数具有相同参数和函数返回值的同名函数。
 
虚析构函数
析构函数的作用是在对象撤销之前做必要的清理现场的工作,当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后调用基类的析构函数。
但如果使用new运算符建立了临时对象,若基类有析构函数,并且定义了一个指向该基类的指针。
在程序用带指针参数的delet运算符撤销对象时,系统只会执行基类的析构函数,而不执行派生类的析构函数。
如果在基类的析构函数声明为虚析构函数,就可以使实现先调用派生类的析构函数,再调用基类的析构函数。

#include<iostream>
using namespace std;
class point {
public:
point(float x = , float y = ); //声明构造函数时指定默认参数
virtual ~point() {
cout << "executing point destructor" << endl;
}
protected:
float x, y;
};
point::point(float a,float b){ //在定义构造函数时可以不指定默认参数
x=a;
y=b;
}
class circle :public point {
public:
circle(float x = , float y = , float r = ) ;
~circle() {
cout << "executing circle destructor" << endl;
}
protected:
float r;
};
circle::circle(float a,float b,float c){
x=a;
y=b;
r=c;
}
int main() {
point *p = new circle;
delete p;
return ;
}
纯虚函数
由于派生类的需要,将基类中某一成员函数定义为虚函数(预留一个函数名),具体功能由派生类定义。
声明虚函数的例子:
virtual float area() {return 0;}
为了简化,可以不写函数体
virtual float area()=0;
注意:纯虚函数没有函数体
      最后面“=0”只起形式上的作用,告诉编译系统“这是纯虚函数”
       这是一个声明语句,最后有分号;
抽象类
有时定义一些类,它们专门作为基类去建立派生类,而不用来定义对象,我们称它们为抽象类(抽象基类)。凡是包含纯虚函数的类都是抽象类,
纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。(不过可以定义指向抽象类数据的指针变量,当派生类成为具体类时,
就可以用这种指针指向派生类的对象,通过该指针调用虚函数,实现多态性)

//虚函数与抽象基类的应用
#include<iostream>
using namespace std;
//声明抽象抽象基类shape
class shape{
public:
virtual float area() const {return ;} //虚函数
virtual float volume() const {return ;}
virtual void shapname() const=; //纯虚函数 };
//声明point类
class point:public shape {
public:
point(float x=,float y=); //声明构造函数
virtual void shapname() const {cout<<"point";}
protected:
float x,y;
};
//定义point
point::point(float a,float b){
x=a;
y=b;
} //声明circle类
class circle:public point{
public:
circle(float x=,float y=,float r=);
virtual float area() const;
virtual void shapname() const {cout<<"circle:";}
protected:
float radius;
};
//定义circle类
circle::circle(float a,float b,float r):point(a,b),radius (r) {} //定义构造函数 float circle::area() const {return radius*radius*3.14;} //声明cylinder类
class cylinder:public circle{
public:
cylinder(float x=,float y=,float r=,float h=);
virtual float area() const;
virtual float volume() const;
virtual void shapname() const{cout<<"cylinder:";}
protected:
float height;
};
//定义cylinder类
cylinder::cylinder(float a,float b,float r,float h):circle(a,b,r),height(h){}
float cylinder::area() const{
return *circle::area()+*radius*3.14*height;
}
float cylinder::volume() const{
return height*circle::area();
}
//main函数
int main(){
point point(,);
circle circle(,,);
cylinder cylinder(,,,);
point.shapename; //静态关联(通过对象名调用虚函数)在编译阶段就可以确定调用的是哪一类的虚函数
shape *pt; //定义基类指针
pt=&point; //使指针指向point类
pt->shapname(); //用指针建立动态关联 (在编译阶段无法从语句本身确定调用的是哪个类的虚函数)
cout<<"\n";
pt=&circle;
pt->shapname();
cout<<"area="<<pt->area()<<"\n"<<endl; pt=&cylinder;
pt->shapname();
cout<<"area="<<pt->area()<<"\n"
<<"volume="<<pt->volume()<<endl;
return ;
}

c++语法笔记(下)的更多相关文章

  1. Java编程基础阶段笔记 day04 Java基础语法(下)

    day04 Java基础语法 (下) 笔记Notes要点 switch-case语句注意 switch-case题目(switchTest5) 循环执行顺序 if-else 实现3个整数排序 Stri ...

  2. SQL基础语法笔记教程整理

    PS:本文适用SQL Server2008语法. 一.关系型数据库和SQL 实际上准确的讲,SQL是一门语言,而不是一个数据库. 什么是SQL呢?简而言之,SQL就是维护和使用关系型数据库中的的数据的 ...

  3. C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

    原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | I ...

  4. 菜鸟教程之学习Shell script笔记(下)

    菜鸟教程Shell script学习笔记(下) 以下内容是学习菜鸟教程之shell教程,所整理的笔记 菜鸟教程之shell教程:http://www.runoob.com/linux/linux-sh ...

  5. 从认识面向对象到构造函数的标准写法(构造函数的继承、多态、ECMA6中新代替语法class) - 下

    笔记一个包含:认识面向对象.构造函数的封装.继承.多态.ECMA6中新代替语法class 下:包括构造函数的继承.多态.ECMA6中新代替语法class 构造函数的继承 从父一级延续下来的属性和功能( ...

  6. SQL 基础语法笔记教程整理

    最近从图书馆借了本介绍 SQL 的书,打算复习一下基本语法,记录一下笔记,整理一下思路,以备日后复习之用. PS:本文适用 SQL Server2008 语法. 首先,附一个发现的 MySQL 读书笔 ...

  7. [python] Pythonic语法笔记

    Pythonic语法笔记 __new__ 在类实例化之前执行的,也就是在init之前执行,可以为这个类写操作.接受的参数不是self而是cls.只有在new方法里返回类才会执行init操作,需要返回父 ...

  8. pyqt样式表语法笔记(下)--原创

    pyqt样式表语法笔记(下) python 启动界面 QSS pyqt 一.启动界面的设置 简单点~说话的方式简单点用一张静态图片作为程序启动界面为例. 原来的语句     python    7行 ...

  9. 02 - Unit07:显示笔记下拉菜单、笔记的分享功能、笔记的删除功能

    显示笔记下拉菜单 笔记的分享功能 发送Ajax请求 绑定事件:绑定分享按钮单击事件 参数获取:笔记ID 发送请求:/share/add.do 服务器处理 ShareController ShareSe ...

随机推荐

  1. scala 递归读取文件夹下所有的指定后缀的文件

    def getFile(file:File): Array[File] ={ val files = file.listFiles().filter(! _.isDirectory) .filter( ...

  2. 将List<E>内对象按照某个字段排序

    主要用到java.util的Collections类 Collections.sort(list); 其中,E必须实现Comparable<E>接口

  3. mac 安装 mysql 5.7

    下载 https://dev.mysql.com/downloads/mysql/5.7.html#downloads 下一步,经过一系列安装步骤后,会跳出一个这样的界面,请注意!!! 上面红框中是你 ...

  4. Java学习日记基础篇(九) —— 集合框架,泛型,异常

    集合框架 有事我们会需要一个能够动态的调整大小的数组,比如说要添加新员工但是数组已经满了,并且数组的大小是在定义的时候定死的,所以我们就需要一个能够动态调整大小的数组或者用链表解决,而java中提供了 ...

  5. ICEM-一种三维Y型网格

    ​原视频下载地址:https://yunpan.cn/cLHD9ewat8v9a  访问密码 0f0f

  6. Android中View大小的确定过程

    View and ViewGroup 安卓中有5种基本的 ViewGroup: FrameLayout RelativeLayout LinearLayout TableLayout Absolute ...

  7. 2018-2019-2 (内附jdk与webgoat完整安装教程)《网络对抗技术》Exp9 Web安全基础 Week13 20165233

    Exp9 Web安全基础 目录 一.基础问题 二.实验步骤 实验前准备:jdk与webgoat的安装 实验点一:SQL 命令注入(Command Injection) 数字型注入(Numeric SQ ...

  8. OpenJudge计算概论-异常细胞检测

    /*======================================================================== 异常细胞检测 总时间限制: 1000ms 内存限制 ...

  9. uboot的仓库在哪里?

    答: https://gitlab.denx.de/u-boot/u-boot# 1. 获取源码 git clone git@gitlab.denx.de:u-boot/u-boot.git Or g ...

  10. NTC热敏电阻基础以及应用和选择(转)

    源:NTC热敏电阻基础以及应用和选择 NTC被称为负温度系数热敏电阻,是由Mn-Co-Ni的氧化物充分混合后烧结而成的陶瓷材料制备而来,它在实现小型化的同时,还具有电阻值-温度特性波动小.对各种温度变 ...