virtual继承机制

virtual修饰的函数可分为虚函数和纯虚函数。
virtual void eat(); //虚函数
virtual void eat() = 0; //纯虚函数

虚函数必须要在当前类中实现,且子类继承的时候,要么就不用声明
纯虚函数在当前类中可实现可不实现,但是如果实现的话,就失去了定义纯虚函数的意义,建议不实现,留给子类去实现。
有纯虚函数的类称为虚类,虚类不能被实例化。

所以其实这样定义等同于java的抽象类的接口。
如果要定义接口,只要实现一个全用virtual void xxx() = 0的纯虚函数实现就行了。

然后对于virtual这个关键字在cpp中的作用,其实如果不用virtual来修饰的父类的函数,子类依然可以继承到,只是用virtual修饰后,在当前类就必须要实现此函数,这是由于如果不加virtual,父类和子类都不需要一定要实现此函数,所以到最后我们拿到一个继承下来的类的时候,这个类的某个方法从当前类一直往父类上找,可能压根就没实现过,这就是有问题的。所以如果有某个方法不想要在父类中实现,那么一定要定义成纯虚函数,这样可以保证我们实例化出一个类时,所有的函数都有实现。
virtual和override的区别:virtual和override都可以覆盖父类的方法。如果用override那么子类和父类指针将各自调用自己实现的方法,而如果用virtual,将子类强转成父类之后,父类指针调用的将会是子类的方法。如下图,父类调用的run是子类实现的。

Man *m = new Man();
Person p = (Person*) m;
m->run();
p->run();

其实我们要看某个方法到底是继承中的哪一层实现的,只需要把注意力放在方法上面,不需要放在类上面。
对于当前类中的某一个方法,如果没有virtual,那么毫无疑问调用的一定是当前类的这个方法。如果有virtual,那么只需要从强制转换的子类开始向上垂直依次找,第一个实现了的就是调用的方法的位置。哪怕当前调用的方法时父类的,当前类中没有声明,没关系,一样的思路从强制转换的子类开始向上依次垂直找,第一个实现的方法就是这个方法的调用的位置。所以我们只需要将注意力放在方法上,没必要放在类上。
思考:virtual的最重要的一点已经在上一段中体现出来了,就是当子类强转成父类之后,父类可以调用子类的方法。所以在设计中,如果某一个方法需要子类来实现,可以使用virtual来实现这个功能。

virtual和不加virtual的区别:
virtual:父类必须实现此函数,子类可不用实现此函数,也不需要定义,可直接调用。
不加virtual:父类可不实现此函数,子类也可以不实现。

然后这里还有一个需要注意的点是:当调用一个实例化的类的一个方法时,会从当前类往上找,直到找到一个实现了的函数就停止。所以这个方法的效果取决于在哪一个类中实现的,因为在不同的类中有可能会有相同的变量,所以在不同的类中去实现这个方法的时候,效果是不一样的,所以不建议取一个名字相同的,会有歧义。在实例化一个子类时,其实在内存里会把他的父类的构造函数都调用一遍,也就是说在内存里有着子类的空间,并且开辟了所有父类的空间。

有纯虚函数的类叫纯类,子类如果没有实现所有的纯虚函数,那么没有实现的纯虚函数也会继承到,所以子类也会是虚类。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值