《随笔十二》—— C++中的 “ 纯虚函数 和 抽象类 ”

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536551/article/details/84561012

目录

抽象类

纯虚函数



抽象类


●   抽象类:  不用于定义对象而只作为一种基本类型用做继承的类,称为抽象类, 由于它常用于做基类, 通常称为抽象基类。 

那么凡是包含纯虚函数的类都是抽象类, 抽象类是一种特殊的类, 是为了抽象和设计的目的而建立的, 处于继承层次结构的较上层。 我们在实际中为了强调一个类是抽象类, 可将该类的构造函数声明为 保护的访问控制权限, 这样我们就不能 在类外创建抽象类的对象,这样我们就可以在抽象类中的派生类中的构造函数对抽象类的成员数据做初始化。

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

抽象类派生出来。抽象类刻画了一组派生类的操作接口的通用语义,这些语义也传给了派生类。  一般而言, 抽象类只描述这组派生类公共的操作接口, 而完整的实现留给派生类。  使用抽象类时应注意的问题:

抽象类只能用作其他类的基类, 不能创建抽象类的对象, 因为它的纯虚函数没有定义功能, 其纯虚函数的实现由派生类给出。

但是可以用 基类指针 或 引用 指向 公有(不能是私有或者 保护的)派生类对象(该派生类对象,必须是个具体类,即派生类实现了抽象类中的同名虚函数,不再是个纯虚函数, 否则的话不可以用基类指针 或 引用 指向),然后我们就可以通过该基类指针 或引用调用虚函数,就可以实现多态操作。

//以下两种方式都不可以给抽象类创建对象
base myBase;  
base mBase = new base;

如果在派生类中对基类的所有(记住是所有,少一个纯虚函数的定义,该派生类还是抽象类)纯虚函数进行了定义, 那么这些函数就被赋予了功能,就可以被调用。 这个派生类就不是个抽象类,而是可以用来定义对象的具体类。   如果在派生类中没有对所有的纯虚函数进行定义,则此派生类仍然是抽象类, 不能用来定义对象。

抽象类不能用作参数类型,函数的返回类型 或 显式转换的类型。


纯虚函数


●  当在基类中不能为虚函数给出一个有意义的实现时, 可以将其声明为纯虚函数。 纯虚函数的实现可以留给派生类来完成。 那么纯虚函数不能被调用, 仅仅起到提供一个与派生类一致的接口的作用。 一般来说, 一个抽象类至少有一个纯虚函数。  纯虚函数的语法为:

virtual 返回类型  标识符 (参数表) = 0 ;

纯虚函数与普通虚函数的定义不同在于书写形式上加了 “ = 0”, 说明在基类中不用定义该函数的函数体, 它并不表示函数返回值为 0, 只起到形式上的作用, 告诉编译系统它是纯虚函数。

下面看一个带有纯虚函数的抽象类的示例程序:

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;

class Shape
{
protected:
	double r;
public:
	Shape(double x)
	{
		r = x;
		cout << "基类的构造函数被调用!" << endl;
	}
	~Shape()
	{
		cout << "基类的析构函数被调用!" << endl;
	}
	virtual void area() = 0;
	virtual void peri() = 0;
};
class Circle:public Shape
{
private:
	int xx;
public:
	Circle(double x, int _xx) :Shape(x), xx(_xx) 
	{
		cout << "派生类的构造函数被调用!" << endl;
	}
	~Circle()
	{
		cout << "派生类的析构函数被调用!" << endl;
	}
	virtual void area()
	{
		cout << "圆的面积为:" << 3.14*r*r << endl;
	}
	virtual void peri()
	{
		cout << "圆的周长为:" << 2 * 3.14*r << endl;
	}
};
int main()
{
	//抽象类不可以创建对象
	/*Shape myShape(5.5);
	Shape *mmShape = new Shape(5.5)*/

	{
		Circle myCircle(5.5, 6);
		Shape *myShape = &myCircle;
		myShape->area();
		myShape->area();
		//myShape->Shape::area(); //不可以调用基类的area()函数,错误
	}
	system("pause");
	return 0;
}

输出结果为:

基类的构造函数被调用!
派生类的构造函数被调用!

圆的面积为:94.985
圆的周长为:34.54

派生类的析构函数被调用!
基类的析构函数被调用!

仔细观察程序,和输出结果。

猜你喜欢

转载自blog.csdn.net/qq_34536551/article/details/84561012
今日推荐