(38.2)虚函数之纯虚函数和抽象类

1.虚析构函数

  • 派生类的对象从内存中撤销时一般先调用派生类的析构函数, 然后再调用基类的析构函数。

  • 但是, 如果用new运算符建立了派生类对象, 且定义了一个基类的指针指向这个对象, 那么当用delete运算符撤销对象时, 系统会只执行基类的析构函数, 而不执行派生类的析构函数, 因而也无法对派生类对象进行真正的撤销清理操作。

  • eg:

Point *pp=new Circle; //基类指针指向派生类
delete pp; //仅执行基类析构函数
  • 如果希望“delete pp”执行Circle的析构函数, 那么基类Point的析构函数要声明为虚函数, 称为虚析构函数
  • 如果将基类的析构函数声明为虚函数, 由该基类所派生的所有派生类的析构函数也都自动成为虚函数, 即使派生类的析构函数与基类的析构函数名字不相同。
  • eg:
#include <iostream>
using namespace std;
class Base
{
	public:
		Base() {}
		virtual ~Base() {};
		virtual void fun()
		{
			cout<<"in class Base!"<<endl;
		}
};

class Derived:public Base
{
	public:
		Derived() { };
		~Derived()//虚函数
		{
			cout<<"the destructor of class Derived!"<<endl;
		}
		void fun()//虚函数
		{
			cout<<"int class Derived!"<<endl;
		}
};

int main()
{
	Base *pTest=new Derived;
	pTest->fun();//调用派生类fun
	delete pTest;//不仅调用基类的析构函数,还调用派生类析构函数
	return 0;
}
  • 当基类的析构函数为虚函数时, 无论指针指的是同一类族中的哪一个类对象, 系统总会采用动态联编, 调用正确的析构函数, 对该对象进行清理。
  • C++支持虚析构函数, 但不支持虚构造函数, 即构造函数不能声明为虚函数。

2.纯虚函数和抽象类

►在许多情况下, 不能在基类中为虚函数给出一个有意义的定义, 这时可以将它说明为纯虚函数(pure virtual function) , 将具体定义留给派生类去做。
纯虚函数的定义形式为:

virtual 返回类型 函数名(形式参数列表)=0;
  • 即在虚函数的原型声明后加上“=0” , 表示纯虚函数根本就没有函数体。

  • 纯虚函数的作用是在基类中为其派生类保留一个函数的名字, 以便派生类根据需要对它进行定义。
    如果在一个类中声明了纯虚函数,而在其派生类中没有对该函数定义, 则该虚函数在派生类中仍然为纯虚函数。

  • 包含有纯虚函数的类称为抽象类(abstract class) 。
    一个抽象类只能作为基类来派生新类, 所以又称为抽象基类(abstract base class);
    抽象类不能定义对象;

  • 如果在派生类中给出了抽象类的纯虚函数的实现, 则该派生类不再是抽象类。 否则只要派生类仍然有纯虚函数, 则派生类依然是抽象类。
    抽象类至少含有一个虚函数, 而且至少有一个虚函数是纯虚函数。

  • eg:

#include <iostream>
using namespace std;
class Sharp//Sharp类, 抽象类,不会定义Charp对象
{
	public:
		virtual double area()=0;//纯虚函数
		virtual double volumn()=0;//纯虚函数
};

class Circle:public Sharp//Circle类表示圆
{
	public:
		Circle(double a):r(a) { }
		virtual double area()//虚函数
		{
			return r*3.1415926*r;
		}
		virtual double volumn()//虚函数
		{
			return 0;
		}
		private:
			double r;
};

class Cylinder:public Circle//Cylinder表示圆柱体
{
	public:
		Cylinder(double a,double b):Circle(a),h(b) { }
		virtual double volumn()//虚函数
		{
			return area()*h;
		}
		private:
			double h;
};

int main()
{
	Circle a(10.0);//定义Circle对象
	Cylinder b(5.6,10.5);//定义Cylinder对象
	cout<<a.area()<<b.volumn()<<endl;//静态联编
	Sharp *pb;//定义基类指针
	pb=&b;//指向Circle对象
	cout<<pb->area()<<","<<pb->volumn()<<endl;//动态联编
	
	return 0;
}

发布了556 篇原创文章 · 获赞 140 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/u011436427/article/details/104175808
今日推荐