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

#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. Java基础系列 - 抽象类,子类继承

    package com.company; /** * 抽象类继承 * 用abstract修饰类就是抽象类 * 用abstract修饰方法就是抽象方法(一般使用比较少) * 抽象类不能被实例化 */ p ...

  2. Jenkins 获取 Git 的提交记录(Change Log)

    工作中用 Jenkins 做 iOS 和 Android 的持续集成,之前实现的是当 git 有新代码提交的时候,就会自动编译并上传安装包到蒲公英,然后自动发送QQ群通知或者讨论组通知给相关小伙伴,方 ...

  3. vue实现element-ui对话框可拖拽功能

    element-ui对话框可拖拽及边界处理 应业务需求,需要实现对话框可拖拽问题,应element-ui没有提供官方支持,于是便参考大神的文章,得出了适合业务需要的解决方案.很多大神给出的代码是没有解 ...

  4. HbuilderX

    HBuilderX入门教程 HX是轻量编辑器和强大IDE的完美结合体.敏捷的性能,清爽的界面,强大的功能和于一身. 本文档面向入门用户,建议初学者仔细研读. 介绍 执着于更快一步的理念,hx的左侧项目 ...

  5. 网络爬虫requests-bs4-re-1

    最近了解了爬虫,嗯--------,有时候会搞得有点头晕. 跟着线上老师实现了两个实例.可以用python下载源代码玩玩,爬淘宝的很刺激,虽然违反了ROBOTS协议. GIT地址

  6. postman测试API

    首先创建环境变量 再次在请求参数中,可以应用环境变量,只需要在地址中引用环境变量即可 将返回的参数设置到环境变量中 如已经设置好环境变量,在认证中,选择Bearer Token,然后设置Token为环 ...

  7. IDEA 不编译java以外的文件

    解决办法:修改pom 文件 <build> <resources> <resource> <directory>src/main/java</di ...

  8. 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_01-用户认证-用户认证流程分析

    1 用户认证 1.1 用户认证流程分析 用户认证流程如下: 访问下面的资源需要携带身份令牌和jwt令牌,客户端可以通过身份认证的令牌从服务端拿到长令牌, 一会要实现认证服务请求用户中心从数据库内来查询 ...

  9. PAT 甲级 1055 The World's Richest (25 分)(简单题,要用printf和scanf,否则超时,string 的输入输出要注意)

    1055 The World's Richest (25 分)   Forbes magazine publishes every year its list of billionaires base ...

  10. PPT做交互效果

    1 做交互效果(点击一个按钮,弹出某个框或者跳转到某个页面)其实就是若干个PPT页面,利用给按钮增加超链接或者动作 达到点击一个按钮 跳转到另外一个PPT的效果. 2 选择一个形状组件(或者其他组件) ...