c++多态

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>

using namespace std;

//什么是多态:
//有多个完全不同的对象,对它们发送同一个消息,它们反应各不相同,分别执行不同的操作。这种情况就是多态现象
//例:甲乙丙3个班都是高二年级,他们有基本相同的属性和行为,但在听到上课铃声时,他们却是走向3个不同班级
//c++中所谓的多态是指:
//由继承产生的相关的但不同的类,其对象对同一消息会作出不同的响应

class Parent
{
public:
    Parent(string name)
    {
        this->name = name;
    }
    //说明父类的这个函数为虚函数
    virtual void func()
    {
        cout << "parent func()......" << endl;
        cout << "this->name:" << this->name << endl;
    }
private:
    string name;
};

class Child :public Parent
{
public:
    Child(string name) :Parent("father")
    {
        this->name = name;
    }
    //当父类中的一个虚函数在子类中被重写,那么执行赋值兼容原则的方法时,便不会去执行父类的方法了,而是去执行被子类重写的方法,这就形成了c++的多态
    //注意:只有子类重定义父类的虚函数时,才叫重写,其他的就直接叫重定义
    virtual void func()//当子类里重写了父类的虚函数时,通常在子类重写的方法前也加上virtual,代表子类中这个函数为重写父类虚函数,提高代码的可读性,但对编译器是没有任何影响的
    {
        cout << "child func()......" << endl;
        cout << "this->name:" << this->name << endl;
    }
private:
    string name;
};

//全局方法,多态的前提的赋值兼容原则,大的可以给小的赋值
//void print(Parent p)当传入的是父类对象时,不会发生多态,尽管子类重写了父类的虚函数,因为传入对象时,这时是重新创建了一个父类对象p,这个父类对象p和传入进来的子类和父类没有任何关系,你调用p类的方法,它当然是执行p对象的方法
//总结:发生多态的三个必要条件
//1.要有继承
//2.子类要有父类的虚函数重写
//3.全局方法中传入的是父类对象的指针或引用,不能是父类的对象,即要存在父类的指针或引用指向子类对象

class Animal
{
public://类中不写权限关键字,默认为私有成员变量
    virtual void roar()
    {
        cout << "animal roar..." << endl;
    }
};

class Dog :public Animal
{
public:
    virtual void roar()
    {
        cout << "dog wangwangwang..." << endl;
    }
};

class People
{
public:
    void say()
    {
        cout << "people bbb..." << endl;
    }
};

void print(Parent &p)
{
    p.func();
}

void roar(People &p, Animal &a)
{
    p.say();
    a.roar();//这儿发生了多态
}

class A
{
public:
    A()
    {
        this->p = new char[64];
        memset(this->p, 0, 64);
        strcpy(this->p, "A string...");//strcpy函数会拷贝一个\0
    }
    virtual void print()
    {
        cout << this->p << endl;
    }
    virtual ~A()
    {
        if (this->p != NULL)
        {
            delete[] p;
        }
        cout << "~A()......" << endl;
    }
private:
    char *p;
};

class B :public A
{
public:
    B()
    {
        this->p = new char[64];
        memset(this->p, 0, 64);
        strcpy(this->p, "B string...");
    }
    virtual void print()
    {
        cout << this->p << endl;
    }
    virtual ~B()
    {
        if (this->p != NULL)
        {
            delete[] p;
        }
        cout << "~B()......" << endl;//子类中创建时会调用父类的构造函数,删除时也会调用父类的析构函数
    }
private:
    char *p;
};

void test1(A &a)//因此传进来的引用在栈区,因此父类A和子类B的析构函数都是自动触发,不需要我们手动回收空间
{
    a.print();//这儿发生了多态
}

void test2(A *a)//因为传进来的指针指向的对象在堆空间,因此堆空间对象的析构函数不会自动触发,需要手动释放
{
    a->print();//这儿发生了多态
    delete a;//这儿如果你不把父类的析构函数改为虚析构函数,那么这儿删除堆空间触发的是父类的析构函数,并不是子类的析构函数,因此这儿也需要发生多态,即把父类的析构函数写成虚析构函数,出发了子类的析构函数就会关联触发父类的析构函数,这样就不会发生内存泄漏了

}

class C
{
public:
    virtual ~C()
    {
        cout << "~C()......" << endl;
    }
};

class D :public C
{
public:
    //当子类对象在堆空间时,回收空间时需要发生多态,这时需要使父类的析构函数变为虚析构函数
    //当子类对象在栈空间时,不需要考虑这些
    virtual ~D()
    {
        cout << "~D()......" << endl;
    }
};

void test3(C *c)
{
    delete c;//发生了多态
}

int main()
{
    Parent p1("parent");
    Child c1("child");
    //下面一段代码虽然传入参数为子类对象,但输出的结果为父类函数输出的结果
    //原因:编译器默认做了一个安全处理。编译器认为不管传递是子类对象还是父类对象,如果统一执行父类的方法则一定成功,所以这儿编译器就调用了父类的方法
    //总结:因此不论传入的是子类对象还是父类对象,使用赋值兼容性原则调用全局函数,执行的一定是父类的方法
    //如何使传入的是子类对象就执行子类对象方法,传入的是父类的对象就执行父类对象的方法?
    //引入虚函数,即在父类的方法前加virtual关键字,虚函数关键字虽然和虚继承关键字一样,但完全是两个意思,它们两没有任何关系
    print(p1);
    print(c1);

    People p2;
    Dog d2;
    roar(p2, d2);

    //联编是指代码相互关联的过程,属于编译器的知识
    //1.静态联编:是程序的匹配、连接在编译阶段实现,也成为早起联编。重载函数使用静态联编
    //2.动态联编:指程序联编推迟到运行时进行,又称为晚期联编。switch语句和if语句使用动态联编,多态对于编译器来讲也是一个动态联编

    B b1;
    test1(b1);
    B *b2 = new B;
    test2(b2);

    cout << endl << endl;

    D *d = new D;
    test3(d);

    //重载,重写,重定义
    //1.重载:一定是同一个作用域下,函数名相同,函数参数类型或个数不同
    //2.重定义:一定发生在继承时的父子类中,子类重定义了父类的函数,函数名和参数返回值完全相同,只是函数体不同
    //3.重写:重写是一种特殊情况的重定义,子类重定义的函数为父类的虚函数时,即被称为重写,重写只有虚函数有关,重写是发生多态的必要条件
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值