初学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;

 

总结:

  1. 一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也不必要定义对象。
  2. 抽象基类与普通基类不同,它一般并不是现实存在的对象的抽象(例如圆形(Circle)就是千千万万个实际的圆的抽象),它可以没有任何物理上的或其他实际意义方面的含义。
  3. 在类的层次结构中,顶层或最上面的几层可以是抽象基类。抽象基类体现了本类族中各类的共性,把各类中共有的成员函数集中在抽象基类中声明。
  4. 抽象基类是本类族的公共接口。或者说,从同一基类派生出的多个类有同一接口。
  5. 区别静态关联和动态关联。如果是通过对象名调用虚函数(如p.area()),在编译阶段就能确定调用的是哪一个类的虚函数,所以属于静态关联。 如果是通过基类指针调用虚函数(如p->area()),在编译阶段无法从语句本身确定调用哪一个类的虚函数,只有在运行时,pt指向某一类对象后,才能确定调用的是哪 一个类的虚函数,故为动态关联。
  6. 如果在基类声明了虚函数,则在派生类中凡是与该函数有相同的函数名、函数类型、参数个数和类型的函数,均为虚函数(不论在派生类中是否用virtual声明)。
  7. 使用虚函数提高了程序的可扩充性。把类的声明与类的使用分离。这对于设计类库的软件开发商来说尤为重要。


 

以上是关于初学C++之虚函数及抽象类的主要内容,如果未能解决你的问题,请参考以下文章

C++性能榨汁机之虚函数的开销

C++之虚函数和虚函数表

冒号课堂阅读笔记OO的多态抽象类型——实中之虚

C++之虚函数

C++之虚函数和多态

虚函数实现原理之虚函数表