C++之多态

多态

#include <iostream>

using namespace std;

class Animal{
public:
    void speak(){
        cout<<"动物在说话"<<endl;
    }
};

class Dog:public Animal{
public:
    void speak(){
        cout<<"狗在汪汪"<<endl;
    }
};

int main()
{
//父类指针 保存 子类空间地址
    Animal *p=new Dog;
    p->speak();

    return 0;
}

打印:

动物在说话

其实用户的需求:p->speak 希望等到的是“狗在汪汪” 而不是“动物在说话”。

要实现用户需求则需要通过虚函数来实现

虚函数

成员函数前加virtual修饰

子类重写父类的虚函数注意:有继承、子类重写父类虚函数(函数名、返回值类型、参数类型个数顺序 必须完全一致)。

#include <iostream>

using namespace std;

class Animal{
public:
    virtual void speak(){
        cout<<"动物在说话"<<endl;
    }
};

class Dog:public Animal{
public:
    void speak(){
        cout<<"狗在汪汪"<<endl;
    }
};

int main()
{
    Animal *p=new Dog;
    p->speak();//打印 狗在汪汪

    return 0;
}

多态条件:有继承、子类重写父类的虚函数,父类指针 指向子类空间。

纯虚函数

虚函数不实现函数体

class Animal
 {
 public:
 //纯虚函数
 virtual void speak(void)=0;
 };

一旦类中有纯虚函数,那么这个类就是抽象类。

抽象类 不能实例化对象。(Object ob;错误)
抽象类 必须被继承 同时 子类 必须重写 父类的所有纯虚函数,否则 子类也是抽象类

抽象类主要的目的是设计类的接口

虚函数和纯虚函数的 区别?
虚函数:virtual修饰 有函数体不会导致父类为抽象类。
纯虚函数:virtual修饰,=0,没有函数体 导致父类为抽象类。子类必须重写父类的所有纯虚函数

虚析构

虚析构:通过父类指针 释放整个子类空间。

#include <iostream>

using namespace std;

class Person{

public:
    virtual void fun(){
        cout<<"Person的fun()"<<endl;
    }

    virtual ~Person(){
        cout<<"Person中的析构函数"<<endl;
    }


};


class Son:public Person{
public:
    void fun(){
        cout<<"Son类的fun()"<<endl;
    }

     ~Son(){
        cout<<"Son的析构函数"<<endl;
    }

};


int main()
{
    Person *p=new Son;
    p->fun();

    delete p;
    return 0;
}

Son类的fun()
Son的析构函数
Person中的析构函数

构造的顺序:父类—>成员---->子类
析构的顺序:子类—>成员---->父类

纯虚析构函数

纯虚析构的本质:是析构函数,各个类的回收工作。而且析构函数不能被继承。

必须为纯虚析构函数提供一个函数体。纯虚析构函数 必须在类外实现

#include <iostream>

using namespace std;

class Person{

public:
    virtual void fun()=0;

    virtual ~Person()=0;

};
//纯虚析构函数 必须在类外实现
Person::~Person(){
    cout<<"Person中的析构函数"<<endl;
}

class Son:public Person{
public:
    void fun(){
        cout<<"Son类的fun()"<<endl;
    }

     ~Son(){
        cout<<"Son的析构函数"<<endl;
    }

};


int main()
{
    Person *p=new Son;
    p->fun();

    delete p;
    return 0;
}

重载、重定义、重写的区别

重载:同一作用域,同名函数,参数的顺序、个数、类型不同 都可以重载。函数的返回值类型不能作为重载条件(函数重载、运算符重载)

重定义:有继承,子类 重定义 父类的同名函数(非虚函数), 参数顺序、个数、类型可以不同。子类的同名函数会屏蔽父类的所有同名函数(可以通过作用域解决)

重写(覆盖):有继承,子类 重写 父类的虚函数。返回值类型、函数名、参数顺序、个数、类型都必须一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值