zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++:纯虚函数和抽象类 | 虚函数和纯虚函数区别

C++ 函数 区别 抽象类
2023-09-27 14:29:24 时间

前言

本文由纯虚函数和抽象类引出工厂模式,继承与多态的内容到达本篇,也基本介绍完了。

纯虚函数概念

纯虚函数(pure virtual function)是指被标明为不具体实现的虚拟成员函数。它用于这样的情况:定义一个基类时,会遇到无法定义基类中虚函数的具体实现,其实现依赖于不同的派生类。

定义纯虚函数的一般格式为:

virtual 返回类型 函数名(参数列表) = 0;

“=0”表明程序员将不定义该函数,函数声明是为派生类保留一个位置。“=0”本质上是将指向函数体的指针定为NULL。

抽象类的概念

首先要了解到:含有纯虚函数的基类是不能用来定义对象的。
纯虚函数没有实现部分,不能产生对象,所以含有纯虚函数的类是抽象类。

  1. 带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。

  2. 抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。

  3. 抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。

  4. 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。

示例
实在不理解抽象类,那么可以这样想:
面向对象设计的类,其目的是为了模拟现实,普通的类意思就是,可以模拟实现动物,家具等具体事物;那么抽象类所模拟的示例有:社会,生活,打工等。
比如有人说,C++太难了,我还是去工地搬砖吧,这样的行为可以用普通的类模拟,设计出搬砖这种类;但有人说,C++太难了,我不学了想去混社会,这个就无法模拟实现出来了,所以就叫做抽象类。

类的分类

在经过继承和多态的学习后,可以总结出类可以分为下面这些:

普通类

有数据,有方法的类

class Object
{
private:
	string name;
public:
	void Print()const {}
};

继承,有虚函数的类

在继承中基类有虚函数,派生类实现基类虚方法,程序运行时产生动态联编的情况

class Object
{
private:
	string name;
public:
	virtual void Print()const {}
};

class Base : public Object
{
private:
	int num;
public:
	virtual void Print()const {}
};

抽象类

基类中有纯虚函数,派生类必须实现基类的纯虚函数的情况,称为抽象类。

class Object
{
private:
	string name;
public:
	void add() {}
	virtual void Print()const = 0;
};

class Base : public Object
{
private:
	int num;
public:
	virtual void Print()const {
		cout << "..." << endl;
	}
};

interface(接口)

在一个抽象类中,只有方法类的集合,即只有纯虚函数的类叫做interface。
在派生类中,必须要重写所有的方法,不然这个派生类也是抽象类。

struct Object
{
	virtual void Print() = 0;
	virtual void Add() = 0;
	virtual void fun() = 0;
};

总结

抽象类的规定
(1)抽象类只能用作其他类的基类,不能建立抽象类对象。
(2)抽象类不能用作参数类型、函数返回类型或显式转换的类型。
(3)可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性。

虚函数和纯虚函数区别

  1. 类里如果声明了虚函数,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被覆盖,这样的话,这样编译器就可以使用后期绑定来达到多态了。纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。

  2. 虚函数在子类里面也可以不重载的;但纯虚函数必须在子类去实现,这就像Java的接口一样。通常把很多函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,但是增加了面向对象的多态性,因为很难预料到父类里面的这个函数不在子类里面不去修改它的实现。

  3. 带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。这样的类也叫抽象类。抽象类和大家口头常说的虚继承基类还是有区别的,在C#中用abstract定义抽象类,而在C++中有抽象类的概念,但是没有这个关键字。抽象类被继承后,子类可以继续是抽象类,也可以是普通类。

虚基类:“virtual”继承的类,也就是说任何类都可以成为虚基类。
抽象类:至少包含一个纯虚函数的类,其不能被实例化,哪怕该纯虚函数在该类中被定义。二者没有任何联系。

虚基类就是解决多重多级继承造成的二义性问题。