C++多态

        多态(polymorphism)的概念:通俗来说,就是多种形态。比如动物会叫,鸡叫起来是“咯咯咯”,鸭叫起来是“嘎嘎嘎”,这就是一种多态,即对同一行为的不同表现

        多态分为编译时多态(静态多态)和运⾏时多态(动态多态),编译时多态(静态多态)主要就是我们前⾯讲的函数重载和函数模板,针对同一对象对同一行为的不同处理带来的不同表现,这⾥我们重点讲运⾏时多态,运⾏时多态,具体点就是去完成某个⾏为(函数),可以传不同的对象就会完成不同的⾏为,就达到多种形态,针对的是不同的对象。

1.多态的定义及实现   

        多态是⼀个继承关系的下的类对象,去调⽤同⼀函数,产⽣了不同的⾏为。注意:必须是引用或指针去调用虚函数才能实现多态,那么什么是虚函数呢?类成员函数前⾯加virtual修饰,那么这个成员函数被称为虚函数。注意⾮成员函数不能加virtual修饰。子类要想实现多态需对父类的虚函数进行重写,派⽣类中有⼀个跟基类完全相同的虚函数(即派⽣类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称派⽣类的虚函数重写了基类的虚函数。(注:其实派生类的虚函数不加virtual也可以构成重载,但为了规范,建议加上)

        以下是多态的一个简单实现:

class  Animal 
{
public:
    void eat(string food)
    {
        cout << "我吃了:" << food << endl;
    }

    void virtual howl()
    {
        cout << "我啥动物都不知道怎么叫?" << endl;
    }

};

class Dog :public Animal
{
public:
    void virtual howl()
    {
        cout << "汪汪汪,咬洗你!" << endl;
    }

};


class Cat :public Animal
{
public:
    void virtual howl()
    {
        cout << "喵~" << endl;
    }

};

class Human :public Animal
{
public:
    void virtual howl()
    {
        cout << "不是,哥们?" << endl;
    }



};

void AnimalHowal(Animal& a)
{
    a.howl();
}





int main()
{
    Animal a1;
    Dog d1;
    Cat c1;
    Human h1;
    AnimalHowal(a1);
    AnimalHowal(d1);
    AnimalHowal(c1);
    AnimalHowal(h1);
    

    return 0;
}

2.关于多态的默认参数问题

        请看以下程序:

 class  Animal 
{
public:
    void virtual eat(string food = "鱼")
    {
        cout << "我吃了:" << food << endl;
    }

    void virtual howl()
    {
        cout << "我啥动物都不知道怎么叫?" << endl;
    }

};



class Dog :public Animal
{
public:
    void virtual howl()
    {
        cout << "汪汪汪,咬洗你!" << endl;
    }

    void virtual eat(string food = "狗粮")
    {
        cout << "我吃了:" << food << endl;
    }

};


int main()
{
    Animal a;
    a.eat();
    Dog d;
    Animal& d1 = d;
    d1.eat();

    return 0;
}

请问以上程序的运行结果是什么?

相信很多同学都会直接回答:我吃了:鱼

                                               我吃了:狗粮

而事实情况可能会让你大跌眼镜:

        这里涉及到一个隐含知识点:派生类在重写虚函数时实际上是重写的它的函数体,参数列表仍沿用的父类,因此默认参数仍使用的是父类的默认参数

3.析构函数的重写

        编译器编译后各类中析构函数的名称统⼀处理成destructor,所以基类的析构函数加了vialtual修饰,派⽣类的析构函数就构成重写

class  Animal 
{
public:
    void virtual eat(string food = "鱼")
    {
        cout << "我吃了:" << food << endl;
    }

    void virtual howl()
    {
        cout << "我啥动物都不知道怎么叫?" << endl;
    }

    virtual ~Animal()
    {
        cout << "调用了Animal的析构" << endl;
    }

};



class Dog :public Animal
{
public:
    void virtual howl()
    {
        cout << "汪汪汪,咬洗你!" << endl;
    }

    void virtual eat(string food = "狗粮")
    {
        cout << "我吃了:" << food << endl;
    }
    ~Dog()
    {
        cout << "调用了Dog的析构" << endl;
        delete[] friends;
    }

    string* friends = new string[10];

};


int main()
{
    Animal* a = new Animal;
    Animal* d = new Dog;

    delete a;
    delete d;
    return 0;
}

        这里Dog中存了需要手动释放的资源friends,如果未对Animal的析构进行重写的话,delete d任然调用的是Animal的析构,friends未被释放,会造成内存泄露

4.override 和 final关键字

        C++11提供了override,可以帮助⽤⼾检测是否重写。如果我们不想让派⽣类重写这个虚函数,那么可以⽤final去修饰。

        

class  Animal 
{
public:
    void virtual eat(string food = "鱼")
    {
        cout << "我吃了:" << food << endl;
    }

    void virtual howl()
    {
        cout << "我啥动物都不知道怎么叫?" << endl;
    }

    virtual ~Animal()
    {
        cout << "调用了Animal的析构" << endl;
    }

};



class Dog :public Animal
{
public:
    void virtual howl()
    {
        cout << "汪汪汪,咬洗你!" << endl;
    }

    void virtual  eat(string food = "狗粮") override
    {
        cout << "我吃了:" << food << endl;
    }
    ~Dog()
    {
        cout << "调用了Dog的析构" << endl;
        delete[] friends;
    }

    string* friends = new string[10];

};
class  Animal 
{
public:
    void virtual eat(string food = "鱼")
    {
        cout << "我吃了:" << food << endl;
    }

    void virtual howl() final
    {
        cout << "我啥动物都不知道怎么叫?" << endl;
    }

    virtual ~Animal()
    {
        cout << "调用了Animal的析构" << endl;
    }

};



class Dog :public Animal
{
public:
    void virtual howl()
    {
        cout << "汪汪汪,咬洗你!" << endl;
    }

    void virtual  eat(string food = "狗粮") 
    {
        cout << "我吃了:" << food << endl;
    }
    ~Dog()
    {
        cout << "调用了Dog的析构" << endl;
        delete[] friends;
    }

    string* friends = new string[10];

};

5.纯虚函数和抽象类

        在虚函数的后⾯写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类,抽象类不能实例化出对象,如果派⽣类继承后不重写纯虚函数,那么派⽣类也是抽象类。抽象类就好像你们的老板,不完成他给定的任务(实现虚函数),你就别想下班qwq

class Boss
{
public:
    void virtual task() = 0;
};

class staff:Boss
{
public:
    string id;

};


int main()
{
    Boss b;
    staff s;

    return 0;
}

class Boss
{
public:
    void virtual task() = 0;
};

class staff:Boss
{
public:
    void virtual task()
    {

        cout << "我想摸鱼~" << endl;
    }


    string id;
};


int main()
{
    staff s;
    s.task();
    return 0;
}

        那么最后,祝大家国庆节快乐,byebye~(诶不是我国庆假怎么只有一天了啊qwq)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值