C++笔记(四)

1.纯虚函数
在基类中仅仅给出声明,不对虚函数实现定义,而是在派生类中实现。这个虚函数称为纯虚函数。普通函数如果仅仅给出它的声明而没有实现它的函数体,这是编译不过的。纯虚函数没有函数体。

语法:纯虚函数需要在声明之后加个=0;

class <基类名>

{

virtual <类型><函数名>(<参数表>)=0; ......

};

2.抽象类
含有纯虚函数的类被称为抽象类。抽象类只能作为派生类的基类,不能定义对象,但可以定义指针。在派生类实现该纯虚函数后,定义抽象类对象的指针,并指向或引用子类对象。

1)在定义纯虚函数时,不能定义虚函数的实现部分;

2)在没有重新定义这种纯虚函数之前,是不能调用这种函数的。

抽象类的唯一用途是为派生类提供基类,纯虚函数的作用是作为派生类中的成员函数的基础,并实现动态多态性。继承于抽象类的派生类如果不能实现基类中所有的纯虚函数,那么这个派生类也就成了抽象类。因为它继承了基类的抽象函数,只要含有纯虚函数的类就是抽象类。纯虚函数已经在抽象类中定义了这个方法的声明,其它类中只能按照这个接口去实现。

3.接口和抽象类的区别

1)C++中我们一般说的接口,表示对外提供的方法,提供给外部调用。是沟通外部跟内部的桥梁。也是以类的形式提供的,但一般该类只具有成员函数,不具有数据成员;

2)抽象类可以既包含数据成员又包含方法。

抽象类的实例1

#include <iostream>
using namespace std;

class Shape
{
public:
    virtual float area()=0;//纯虚函数,获得面积
};
//公有继承自Shape类
class Circle:public Shape
{
private:
    float radius;
public:
    Circle(float r=0.0):radius(r){}

    // 必须复写父类的纯虚函数
    //实现声明实现两个基类的函数,声明的时候需要加virtual关键字,实现的时候就不需要加virtual关键字了。
   virtual float area();
};
//实现的时候就不需要加virtual关键字了。
float Circle::area()
{
    return 3.14*radius*radius;
}


class Rectangle:public Shape
{
private:
    float width;
    float height;

public:
    Rectangle(float w=0, float h=0):width(w), height(h){}

    // 必须复写父类的纯虚函数
    virtual float area(){return width*height;}

};

// 设计一个函数,可以输出任意形状的面积
void showArea(Shape *r)
{
    cout << "面积:" << r->area() << endl;
}
int main()
{
    Shape *pShape=NULL;//定义了一个抽象类的指针,注意抽象类不能定义对象但是可以定义指针

    pShape = new Circle(2.2); //基类指针指向派生类的对象Circle c(2);

   showArea(pShape);

    delete pShape; //释放了CCirle对象所占的内存,但是指针是没有消失的,它现在就是一个野指针,我们在使用之前必须对它赋值
    pShape = new Rectangle(2.0, 1.0); //基类指针指向派生类的对象Rectangle r(2,3);

    showArea(pShape);

    return 0;
}



抽象基类的实例2

#include <iostream>
using namespace std;

// 抽象基类: 是一个不完整的类
class F
{
public:
    // 普通的虚函数,他有默认行为
    virtual void fly(){cout<<"默认飞行模式"<<endl;}

    // 纯虚函数,他不提供默认的行为
    // 这是一个只有接口,没有内容的不完整的函数
    virtual float area()=0;
};

class A:public F
{
public:
     // 掩盖了父类的fly, 此处的virtual可以省略
     void fly(){cout << "直升机盘旋" << endl;}

     // 必须要复写父类的纯虚函数,否则A也成为抽象基类
     float area(){return 1.2;}
};

class B : public F
{
public:
    // 掩盖了父类的fly
    void fly(){cout << "轰炸机实弹飞行" << endl;}

    // 由于没有复写父类的纯虚函数,B也成为抽象基类,不可以定义对象
    float area(){return 2.1;}
};

// 王牌飞行员
class polit
{
public:
    // 通过父类的指针或者引用,可以访问子类的虚函数版本
    // 如果子类没有重写虚函数fly的版本,那么f->fly()就是父类的版本
    void drivePlane(F *f){f->fly();}
};

int main()
{
       polit Jack;

        F *x;

        // 如果是直升机,那么就按照直升机来非
        x = new A;
        Jack.drivePlane(x);

        // 如果是轰炸机,那么就按照轰炸机来飞
         x = new B;
        Jack.drivePlane(x);

        // 以后不管是什么类型的飞机,只要是飞行器的子类他都能开
//        x = new ????;
//        Jack.drivePlane(x);
        return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值