C++语言基础(13)-抽象类和纯虚函数
一.基本语法
在C++中,可以将虚函数声明为纯虚函数,语法格式为:
virtual 返回值类型 函数名 (函数参数) = ;
纯虚函数没有函数体,只有函数声明,在虚函数声明的结尾加上=0,表明此函数为纯虚函数。
最后的=0并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”。
包含纯虚函数的类称为抽象类(Abstract Class)。之所以说它抽象,是因为它无法实例化,也就是无法创建对象。原因很明显,纯虚函数没有函数体,不是完整的函数,无法调用,也无法为其分配内存空间。
抽象类通常是作为基类,让派生类去实现纯虚函数。派生类必须实现纯虚函数才能被实例化。
二.使用方法
#include <iostream>
using namespace std; //线
class Line{
public:
Line(float len);
virtual float area() = ; // 纯虚函数
virtual float volume() = ; // 纯虚函数
protected:
float m_len;
};
Line::Line(float len): m_len(len){ } //矩形
class Rec: public Line{
public:
Rec(float len, float width);
float area();
protected:
float m_width;
};
Rec::Rec(float len, float width): Line(len), m_width(width){ }
float Rec::area(){ return m_len * m_width; } //长方体
class Cuboid: public Rec{
public:
Cuboid(float len, float width, float height);
float area();
float volume();
protected:
float m_height;
};
Cuboid::Cuboid(float len, float width, float height): Rec(len, width), m_height(height){ }
float Cuboid::area(){ return * ( m_len*m_width + m_len*m_height + m_width*m_height); }
float Cuboid::volume(){ return m_len * m_width * m_height; } //正方体
class Cube: public Cuboid{
public:
Cube(float len);
float area();
float volume();
};
Cube::Cube(float len): Cuboid(len, len, len){ }
float Cube::area(){ return * m_len * m_len; }
float Cube::volume(){ return m_len * m_len * m_len; } int main(){
Line *p = new Cuboid(, , );
cout<<"The area of Cuboid is "<<p->area()<<endl;
cout<<"The volume of Cuboid is "<<p->volume()<<endl; p = new Cube();
cout<<"The area of Cube is "<<p->area()<<endl;
cout<<"The volume of Cube is "<<p->volume()<<endl; return ;
}
运行结果:
The area of Cuboid is 2200
The volume of Cuboid is 6000
The area of Cube is 1350
The volume of Cube is 3375
本例中定义了四个类,它们的继承关系为:Line --> Rec --> Cuboid --> Cube。
Line 是一个抽象类,也是最顶层的基类,在 Line 类中定义了两个纯虚函数 area() 和 volume()。
在 Rec 类中,实现了 area() 函数;所谓实现,就是定义了纯虚函数的函数体。但这时 Rec 仍不能被实例化,因为它没有实现继承来的 volume() 函数,volume() 仍然是纯虚函数,所以 Rec 也仍然是抽象类。
直到 Cuboid 类,才实现了 volume() 函数,才是一个完整的类,才可以被实例化。
抽象类主要有以下两个用途:
1.定义一个抽象基类,只完成部分功能,未完成的功能交给子类去实现。
2.抽象基类除了约束派生类的功能,还可以实现多态。请注意第 51 行代码,指针 p 的类型是 Line,但是它却可以访问派生类中的 area() 和 volume() 函数,正是由于在 Line 类中将这两个函数定义为纯虚函数;如果不这样做,51 行后面的代码都是错误的。
关于纯虚函数的其它说明:
1.一个纯虚函数就可以使类成为抽象基类,但是抽象基类中除了包含纯虚函数外,还可以包含其它的成员函数(虚函数或普通函数)和成员变量。
2.只有类中的虚函数才能被声明为纯虚函数,普通成员函数和顶层函数均不能声明为纯虚函数。如下例所示:
//顶层函数不能被声明为纯虚函数
void fun() = ; //compile error class base{
public :
//普通成员函数不能被声明为纯虚函数
void display() = ; //compile error
};
C++语言基础(13)-抽象类和纯虚函数的更多相关文章
- C++中的抽象类及纯虚函数的实现与否
1.含有纯虚函数的叫抽象类 2.抽象类(一般是基类)中的纯虚函数无论函数体实现与否,都没有关系,系统会自动忽略 3.继承自抽象类的子类,必须要实现父类的纯虚函数才可以实例化对象 4.抽象类不允许实例化 ...
- 《挑战30天C++入门极限》类的分解,抽象类与纯虚函数的需要性
类的分解,抽象类与纯虚函数的需要性 为了不模糊概念在这里我们就简单的阐述一下类的分解,前面的教程我们着重讲述了类的继承,继承的特点就是,派生类继承基类的特性,进行//站点:www.cndev- ...
- c++抽象类,纯虚函数
- C++基础 (7) 第七天 多态的原理 纯虚函数和抽象类 依赖倒置原则
1 昨日回顾 2 多态的原理 1 要有继承 2 要有子类重写父类的虚函数 3 父类指针(或者引用)指向子类对象 (动态联编 虚函数表 3 证明vptr指针的存在 4 vptr指针在构造父类的时候是分步 ...
- C++ 纯虚函数与抽象类——virtual 和纯说明符 “=0”
什么时候使用纯虚函数 某些类,在现实角度和项目角度都不需要实例化(不需要创建它的对象),这个类中定义的某些成员函数只是为了提供一个形式上的接口,准备上子类来做具体的实现.此时这个方法就可以定义为&qu ...
- c++虚函数,纯虚函数,抽象类,覆盖,重载,隐藏
C++虚函数表解析(转) ——写的真不错,忍不住转了 http://blog.csdn.net/hairetz/article/details/4137000 浅谈C++多态性 http://bl ...
- c++,纯虚函数与抽象类
1.纯虚函数的定义: (1)虚函数被“初始化”为0的函数.声明纯虚函数的一般形式是virtual 函数类型 函数名(参数表列) =0;(2)纯虚函数没有函数体:(3)最后面的“=0”并不表示函数返回值 ...
- C++虚函数virtual,纯虚函数pure virtual和Java抽象函数abstract,接口interface与抽象类abstract class的比较
由于C++和Java都是面向对象的编程语言,它们的多态性就分别靠虚函数和抽象函数来实现. C++的虚函数可以在子类中重写,调用是根据实际的对象来判别的,而不是通过指针类型(普通函数的调用是根据当前指针 ...
- C++基础--虚函数和纯虚函数
虚函数的一种重要的应用是在子类重写父类方法上,一般都是在父类中声明的时候用关键字virtual修饰. 在C++中,一个父类的对象指针是可以指向子类的实例化对象,这个时候可以用该对象指针来访问父类的成员 ...
随机推荐
- Problem W: 零起点学算法21——求平均值
#include<stdio.h> int main() { int a,b,c; scanf("%d %d %d",&a,&b,&c); pr ...
- 优化apk
1.首先找到Sdk的位置 2.在电脑中找到Sdk之后点击->bulid-tools 3.点击23.0.3,将需要优化的apk复制到23.0.3的目录下(比如aa.apk) 4.回到23.0.3之 ...
- IO多路复用 select、poll、epoll
什么是IO多路复用 在同一个线程里面, 通过拨开关的方式,来同时传输多个(socket)I/O流. 在英文中叫I/O multiplexing.这里面的 multiplexing 指的其实是在单个线程 ...
- mysql-connector-java-6日期存储时差的问题解决方法
在my.ini文件中的[mysqld]下面加入 default-time_zone = '+8:00' 重启mysql 修改driver连接路径 这样日期保存到mysql就是正确的了,但是mysql- ...
- javascript设定指定元素的父结点的孙子节点的属性
window.onload=function(){ var allerror_a = document.getElementsByClassName("popup_link"); ...
- 关于 Delphi 中流的使用(2) 用 TFileStream(文件流) 读写
TStream 是一个抽象的基类, 不能直接生成对象. 在具体的应用中, 主要使用它的子孙类:TFileStream: 文件流TStringStream: 字符串流TMemoryStream: 内存流 ...
- cdev结构体及其相关函数
一.在Linux2.6内核中一个字符设备用cdev结构来描述,其定义如下: struct cdev { struct kobject kobj; struct module *owner; //所属模 ...
- typeof、instanceof与isPrototypeOf()的差异与联系
一.typeof 1.typeof的意义及作用: 我们知道ECMAScript中有5种简单(基本)数据类型:Undefined.Null.Boolean.Number.String,以及一种引用数据类 ...
- scrapy-splash抓取动态数据例子九
一.介绍 本例子用scrapy-splash抓取众视网网站给定关键字抓取咨询信息. 给定关键字:个性化:融合:电视 抓取信息内如下: 1.资讯标题 2.资讯链接 3.资讯时间 4.资讯来源 二.网站信 ...
- java源码阅读ArrayBlockingQueue
1类签名与简介 public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQ ...