初学C++之虚函数及抽象类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初学C++之虚函数及抽象类相关的知识,希望对你有一定的参考价值。
一、虚函数
在同一类中是不能定义两个名字相同、参数个数和类型都相同的函数的,否则就是“重复定义”。但是在类的继承层次结构中,在不同的层次中可以出现名字相同、参数个数和类型都相同而功能不同的函数。而虚函数的作用,就是让我们在基类和派生类中调用同名函数。
在程序中不是通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用它们。
举个例子:
假如我们定义了一个基类Shape
class Shape { public: void area();
Shape()=default;
Shape(int x,int y,int z):wid(x),len(y),rad(z) {}
~Shape()=default; private: int wid,len,rad; }
其中area函数用于计算面积,比如说矩形和圆,那么接下来我们就需要定义两个派生类Circle,Rectangle。但是由于基类中的area函数需要调用的是Shape中的三个私有元素。在派生类中无法调用,那么每次调用时,就得在派生类中给其另外赋值。
可是,如果将area定义为虚函数,那么在每个派生类中则可以重载,并且自定义其功能。
class Shape { public: virtual double area()=0; //define abstract class and virtual funtion Shape() { wid = len = rad = 0; } Shape(int a, int b, int c) :wid(a), len(b), rad(c) {} ~Shape() = default; protected: int wid, len, rad; };
class Rectangle :public Shape { public: Rectangle() { wid = len = 0; } Rectangle(int a, int b) :wid(a), len(b) {} virtual double area() { return wid*len; } protected: int wid, len, rad; };
class Circle :public Shape { public: Circle() { rad = 0; } Circle(int a) :rad(a) {} virtual double area(){ return (double)Pi*rad*rad; } protected: int rad; };
...
Rectangle A(wid, len); Rectangle *p = &A; //define a pointer,dynamic cout << "The area is:" <<p->area(); Circle C(rad); Circle *p = &C; cout << "The square is:" << p->area();
二、抽象类
什么是抽象类?个人简单理解,就是在类中含有纯虚函数。
例如上面例子中,类Shape中定义了纯虚函数:virtual double area()=0;
总结:
- 一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也不必要定义对象。
- 抽象基类与普通基类不同,它一般并不是现实存在的对象的抽象(例如圆形(Circle)就是千千万万个实际的圆的抽象),它可以没有任何物理上的或其他实际意义方面的含义。
- 在类的层次结构中,顶层或最上面的几层可以是抽象基类。抽象基类体现了本类族中各类的共性,把各类中共有的成员函数集中在抽象基类中声明。
- 抽象基类是本类族的公共接口。或者说,从同一基类派生出的多个类有同一接口。
- 区别静态关联和动态关联。如果是通过对象名调用虚函数(如p.area()),在编译阶段就能确定调用的是哪一个类的虚函数,所以属于静态关联。 如果是通过基类指针调用虚函数(如p->area()),在编译阶段无法从语句本身确定调用哪一个类的虚函数,只有在运行时,pt指向某一类对象后,才能确定调用的是哪 一个类的虚函数,故为动态关联。
- 如果在基类声明了虚函数,则在派生类中凡是与该函数有相同的函数名、函数类型、参数个数和类型的函数,均为虚函数(不论在派生类中是否用virtual声明)。
- 使用虚函数提高了程序的可扩充性。把类的声明与类的使用分离。这对于设计类库的软件开发商来说尤为重要。
以上是关于初学C++之虚函数及抽象类的主要内容,如果未能解决你的问题,请参考以下文章