C++多态,不止虚函数虚表

一:胡聊时间

寒假也结束了,这几天没写博客,是因为玩了胡闹厨房,有一说一挺有趣的,如果你有朋友的话。胡说八道时间就结束吧,今天就拿胡闹厨房的菜来举例多态吧,来模拟一下游戏菜的各种状态、

二:多态、

概念

        概念,我不是很喜欢这种条条框框的东西,大抵就是完成某一个行为时,不同的对象会有不同的状态。

常规多态(类型无关)

        我们拿胡闹厨房举例的话,食物都会有做好,糊了等等几个状态对么?我们设置Food基类用虚函数写一个糊掉了的函数,在子类继承后可以重写Flop函数,也就是所谓的多态,这个是常规的多态.

#include<iostream>

class Food
{
public:
    virtual void Flop() const
    {
        std::cout << "食物糊了" <<std:: endl;
    }
};
class Fish:public Food
{
public:
    void Flop() const override 
    {
        std::cout << "鱼肉糊了" << std::endl;
    }
};
class Hamburg:public Food
{
public:
    void Flop() const override
    {
        std::cout << "汉堡糊了" << std::endl;
    }
};
void Print(const Food& food)
{
    food.Flop();
}
int main()
{
    Fish fish;
    Hamburg burg;
    Print(fish);
    Print(burg);
}

从上面可以看出来,这种多态的本质就是与类型无关, 像鱼肉(class Fish)和汉堡(class Hamburg)都是继承于食物(class Food),所以在Print函数调用时我们可以把它们转成他们的基类Food进行调用,再调用Flop方法,就会调用子类重写的两个方法,从而实现了多态,所以说与类型无关的.实现多态虚函数只是一种方式,但这种方式是最常用且简单的,也方便扩展.

        那我们不用继承可以写一个类似的与类型无关的多态么?我们将它换成枚举类型试试:

非继承多态

#include<iostream>
enum Food_Type
{
    un_Set,Fish,Hamburg,
};
class Food
{
public:
    Food(Food_Type food_type) :food_type(food_type) {}
     void Flop() const
     {
         switch (food_type)
         {
         case un_Set:
             std::cout << "un_Set" << std::endl;
             break;
         case Fish:
             std::cout << "鱼肉糊了" << std::endl;
             break;
         case Hamburg:
             std::cout << "汉堡糊了" << std::endl;
             break;
         default:
             std::cout << "肖战糊了" << std::endl;
             break;
         }
     }
private:
    Food_Type food_type;
};
void Print(const Food& food)
{
    food.Flop();
}
int main()
{
    Food Fish(Food_Type::Fish);
    Print(Fish);
}

我们通过这种方法也能实现多态,但这段代码明显没有面向对象极其难扩展,若加了两道菜不见要改枚举类型,也要在类内添加相应食物代码.这段代码是运行时的多态.

静态多态

        那我们是否可以不使用虚函数完成多态呢?

#include<iostream>
class Food
{
public:
     void Flop() const
    {
        std::cout << "食物糊了" <<std:: endl;
    }
};
class Fish:public Food
{
public:
    void Flop() const  
    {
        std::cout << "鱼肉糊了" << std::endl;
    }
};
class Hamburg:public Food
{
public:
    void Flop() const 
    {
        std::cout << "汉堡糊了" << std::endl;
    }
};
template<typename F_T>
void Print(const F_T &food)
{
    food.Flop();
}
int main()
{
    Fish fish;
    Hamburg hamburg;
    Print(fish);
    Print(hamburg);
}

这里我们运用了函数模板的实参推导,英文叫做argument deduction这里我们不具体展开讲这个,使用这个方法后就可以实现一个简单的静态多态.

        说到静态多态很多都会提到CRTP这个东西(Curiously Recurring Remplate Pattern)翻译过来叫一种奇特的模板方式.那么  CRTP有什么不同呢?

CRTP

#include<iostream>
template<typename Derived>
class Food
{
public:
     void Flop() const
     {
        static_cast<Derived*>(this)->Flop();
     }
     void PrintCount()
     {
         std::cout << FlopCount << std::endl;
     }
protected:
    static int FlopCount;
};
template<typename Derived> int Food<Derived>::FlopCount = 0;
class Fish:public Food<Fish>
{
public:
    Fish()
    {
        FlopCount++;
    }
    void Flop() const  
    {
        std::cout << "鱼肉糊了" << std::endl;
    }
    ~Fish()
    {
        FlopCount--;
    }
};
class Hamburg:public Food<Hamburg>
{
public:
    Hamburg()
    {
        FlopCount++;
    }
    void Flop() const 
    {
        std::cout << "汉堡糊了" << std::endl;
    }
    ~Hamburg()
    {
        FlopCount--;
    }
};
template<typename F_T>
void Print(const F_T& food)
{
    food.Flop();
}
int main()
{
    Fish fish1;
    Fish fish2;
    Hamburg hamburg;
    fish1.PrintCount();
    hamburg.PrintCount();
    Print(fish1);
    Print(hamburg);
}

看起来和之前代码变化不大是么,这里多添加了个糊掉的数量方便我们理解,这里表面上我们的Fish和Hambuger共用同一个基类,但实际上他们是两个不同的类,Fish继承了Food<Fish>这个类,Hambuger继承了Food<Hambuger>这个类,是两个不同的类,我们可以通过FlopCount验证.

可以看到fish打印出是2,hamburg打印出是1,所以实际上他们不是用共同的一个基类.以上就是CRTP的方法,没有用到虚函数虚表就实现了多态,好消息是节省了一些开销,但如果想把他们加入到同一个容器里,不免的还是需要用到虚函数虚表.

总结

        以上就是简单介绍了下C++实现多态的几种方法,希望大家看后不要还是别人一问,C++多态是什么,就说虚函数虚表,哈哈哈,还有CRTP,静态多态,非继承多态等等.还有一个问题,胡闹厨房4颗星是真的有正常人能打出来么,我觉得吧有点不可能.

        一切为KNGG一名普通大学生编写,希望有疑惑不对的地方还是欢迎您指正!!!!!!!!!!! 

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KNGG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值