C++ 类(多态(1))

文章概述

1.多态出现的背景(赋值兼容性原则遇上函数重写);
2.多态理论联系实际;
3.多态成立的3个条件;
4.多态的理论基础;
5.多态的C++实现以及多态的实现效果;
6.虚析构函数;


多态出现的背景(赋值兼容性原则遇上函数重写)

a. 函数重写: 子类中定义与父类原型相同的函数;函数重写发生在父类与子类之间。
b. 如果子类中定义了与父类中原型相同的函数会发生什么?
父类中被重写的函数依然会被继承给子类,默认情况下父类的函数会被子类中重写的函数隐藏,通过父类名+::可以访问到父类中被隐藏的函数。
c. 赋值兼容性原则遇上函数重写:

class A
{
public:
    int a; 
public:
    A()
    {
        a = 5;
        cout << "A" << endl;
    }
    void printF()
    {
        cout << a << "A" << endl;
    }
};

class B:public A
{
public:
    int b;
public:
    B()
    {
        b = 10;
        cout << "B" << endl;
    }
    void printF()
    {
        cout << b << "B" << endl;
    }
};

int main()
{
    B b;
    A* a = &b;
    a->printF();    //调用的是A(父类)

    return 0;
}

对于这个现象的分析:
C++是静态联编的语言。编译时,编译器自动的根据左边的类型判断是哪个类型的对象。
这个现象虽然没有错,但是不符合我们的新需求(根据对象的实际类型确定函数调用,如果父类指针指向的是子类对象,则会调用子类的函数;如果父类指针指向的是父类对象,则会调用父类的函数)。这时候产生多态(同样的调用语句产生不一样的表现效果)。
C++中通过virtual关键字对多态进行支持;使用virtual声明的函数被重写后即可展现多态特性。
这里写图片描述


多态理论联系实际

完整具体的分析上面现象的产生:
a. C++是静态编译类型的语言;
b. 编译的时候,编译器自动根据指针的类型判断指向的是一个什么样的对象,所以编译器认为父类指向的是父类的对象;
c. 由于程序没有运行,所以不知道父类指针指的是父类还是子类的对象。从安全的角度,C++编译器假设父类指针指向的是父类对象,因此编译的结果为父类的成员函数。这种特性就是静态编译。


多态成立的3个条件

(父类的同名函数中加virtual,子类的同名函数可以加也可以不加)
a. 要有继承:
b. 要有虚函数重写;
c. 父类指针(引用)指向子类对象。

class A
{
public:
    int a; 
public:
    A()
    {
        a = 5;
        cout << "A" << endl;
    }
    virtual void printF()
    {
        cout << a << "A" << endl;
    }
};

class B:public A   //继承
{
public:
    int b;
public:
    B()
    {
        b = 10;
        cout << "B" << endl;
    }
    virtual void printF()  //虚函数重写
    {
        cout << b << "B" << endl;
    }
};

int main()
{
    B b;
    A* a = &b;      //父类指针指向子类
    a->printF();    

    return 0;
}

多态的理论基础

a. 联编: 一个程序模块,代码之间相互关联的过程。
b. 静态联编: 程序之间的匹配,连接在编译阶段实现,也称为早期绑定。函数重载就是静态联编的机制。
c. 动态联编: 程序联编推迟到运行时进行,又称为晚期绑定。if和swicth就是动态联编的机制。


多态的C++实现以及多态的实现效果

virtual关键字告诉编译器要支持多态,不要根据指针的类型判断如何调用函数,而是根据指针指向的实际对象类型判断如何调用函数。用virtual修饰的成员函数称为虚函数。虚函数分为两类: a.一般的虚函数; b.纯虚函数。
多态的表现效果: 同样的调用语句有多种不同的表现形态。


虚析构函数

(delete释放的是在堆上开辟的内存空间)
虚析构函数: 通过父类的指针释放所有的子类资源(将子类的析构函数全部执行一遍)

class A
{
public:
    int a; 
public:
    A()
    {
        a = 5;
        cout << "A" << endl;
    }
    virtual void printF()
    {
        cout << a << "A" << endl;
    }
    virtual ~A()
    {
        cout << "~A" << endl;
    }
};

class B:public A   //继承
{
public:
    int b;
public:
    B()
    {
        b = 10;
        cout << "B" << endl;
    }
    virtual void printF()  //虚函数重写
    {
        cout << b << "B" << endl;
    }
    ~B()
    {
        cout << "~B" << endl;
    }
};

int main()
{
    B* b = new B;
    A* a = b;
    //通过父类的指针释放子类的资源,基类采用虚析构函数
    delete a;
    return 0;
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值