【笔记整理】我们仍未知道那天所用的虚函数的原理
来源:互联网 发布:猪八戒局域网考试软件 编辑:程序博客网 时间:2024/05/16 18:15
一、什么是虚函数
在c++的一个类中,如果一个函数前用了virtual关键字,那么这就是一个虚函数
一个非常简单的示例
private: int i;public: base() : i(0){}; base(int num) : i(num){}; ~base(){}; virtual void printI();//<-这个就是虚函数!!!!!! void print();};
注:
√ 构造函数不能是虚函数:如果是把存在的派生类地址给基类指针,那么早就构造好了;如果用new,似乎不涉及基类指针,相当于生成一个派生类,之后再把派生类地址给指针。
√ 析构函数建议写成虚函数
二、虚函数有什么用
当你的基类和(多个)派生类中有同名函数时,你可以用虚函数确定调用哪一个类的该名函数。
如果用基类的指针指向派生类(upcasting),这时候调用某一派生类和基类同名函数,会直接调用基类的该函数。
若要调用派生类的该函数,就要把基类中该函数写成虚函数
三、通过具体例子来理解虚函数
如果是虚函数,则√
当用指针指向派生类时,调用的是哪个函数
所得结果
L1
base : 12
L2
L2 : 21
L2
base : 23
代码
main.cpp
#include<iostream>#include"cbase.h"int main(){ base B(1), *pB; Level1 Lev1(11,12), *p1; Level2 Lev2(21,22,23); pB = &Lev1; p1 = &Lev2; //base指向Level1 pB->print(); //base中为virtual,向上到派生类的同名函数、调用L1中的print() pB->printI(); //指针的类型类中的该函数为非虚函数,直接调用该非虚函数 //Level1指向Level2 p1->print(); p1->printI(); //因为Level1中的两个函数都是虚函数,所以都调用的L2中的同名函数 //base指向Level2 pB = &Lev2; pB->print(); //从basez中的虚函数一路向上,调用L2的同名函数 pB->printI(); //虽然L1是虚函数,但这是base类的指针 //base中该函数为非虚函数,调用base中函数 return 0;}
cbase.h
//// cbase.h// classwork//// Created by 陈天乐 on 16/12/22.// Copyright (c) 2016年 陈天乐. All rights reserved.//#ifndef classwork_cbase_h#define classwork_cbase_hclass base{private: int i;public: base() : i(0){}; base(int num) : i(num){}; ~base(){}; void printI(); virtual void print();};class Level1 : public base{private: int L1;public: Level1() : L1(0),base(){}; Level1(int a) : L1(a),base(){}; Level1(int a, int b) : L1(a),base(b){}; ~Level1(){}; virtual void printI(); virtual void print();};class Level2 : public Level1{private: int L2;public: Level2() : L2(0),Level1(){}; Level2(int a) : L2(a),Level1(){}; Level2(int a, int b) : L2(a),Level1(b){}; Level2(int a, int b, int c) : L2(a), Level1(b,c){}; ~Level2(){}; void printI(); virtual void print();};#endif
cbase.cpp
//// cbase.cpp// classwork//// Created by 陈天乐 on 16/12/22.// Copyright (c) 2016年 陈天乐. All rights reserved.//#include "cbase.h"#include<iostream>void base::printI(){ std::cout << "base : " << i << std::endl;}void base::print(){ std::cout << "base" << std::endl;}void Level1::printI(){ std::cout << "L1 : " << L1 << std::endl;}void Level1::print(){ std::cout << "L1" << std::endl;}void Level2::printI(){ std::cout << "L2 : " << L2 << std::endl;}void Level2::print(){ std::cout << "L2" << std::endl;}
四、阅读学习其他博客的理解和总结
- 关于多态的理解:同一消息(调用函数),不同方法(不同的函数体)
- C++中运行时的多态性主要是通过虚函数来实现的
- 虚函数令函数调用与函数体之间的联系在运行时才建立
- 虚可以理解为,在动态调用的时候,这个函数是隐藏的。要去找最表面的一个。
- 若在基类中显式声明了虚函数,之后的派生类中的同名函数会自动变成虚函数。
知道了这一点后我有一个疑惑:按照这个原理,如果我再增加一个L3层,用L2的指针指向L3并且调用F2,依然会调用L3自己的printI。
验证了一下没有错误。
当一个类中存在一个虚函数,这个类的所有子类的同名都自动变为虚函数
绿色代表,会调用指针的类型的F1
黄色代表,会调用指针指向的类型的F1 - 只有公有派生类才能使用基函数(赋值兼容)
- 虚函数必须是成员函数,不能是友元函数、静态成员函数、内联函数(可能出题)具体为什么(还没深入研究qwq,似乎是虚函数涉及到对象内部)
改错题
virtual void F1() const;
- 纯虚函数的概念:virtual void F1() = 0;//这就是一个纯虚函数
其中的= 0 只是一个标记。纯虚函数不在实现文件里定义。
纯虚函数不能被调用(那它能做什么??)
拥有纯虚函数的类会变成抽象类
抽象类只能作为基类,不能作为派生类
因为抽象类自己不能生成对象。只有继承了这个抽象类的派生类可以生成对象。
纯虚函数用来规范派生类的行为,提高安全性,可以理解为接口(?我对接口还不是很理解)
纯虚函数的意义,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但类无法为纯虚函数提供一个合理的缺省实现。所以类纯虚函数的声明就是在告诉子类的设计者,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它”。
参考资料:
C++之多态性与虚函数
C++的精髓——虚函数
虚函数和纯虚函数的区别
知乎:c++虚函数的作用是什么?
其他的一些东西
1.
2.
使用虚函数能够简化写代码的过程,但是对提高程序运行效率没有帮助
因为虚函数实现的功能你也可以自己实现,但是写起来很麻烦,c++直接帮你写好了虚函数的机制
- 【笔记整理】我们仍未知道那天所用的虚函数的原理
- 10677 我们仍未知道那天所看见的花的名字
- java我们知道的那点事
- 可知道我们十指交缠的那一夜;我们誓言到老的那一夜
- 我们说真话的那天
- 你仍未知道那些有关 Activity典型、异常情况下的生命周期解析
- 合理的配置我们所用的IDE
- 知道你的那天
- 那一年的我们
- 我所用的PHP函数
- C++你仍不知道的事
- 我们平常所用的内存,你真的了解吗?
- 我们的那一点一滴:迷路
- 那半年我们的C++
- 那一年的我们——那一年我们
- 再缜密的设计,我们也很难保证完全没有bug,之所以仍未发现,只是激活这个bug的条件还没到来
- ABAP开发所用到的函数
- php----正则表达式所用到的函数
- A+B也疯狂
- 1.编写第1个Android应用程序实现按钮和复选框
- Redis入门
- 2016.12.22 学习日记-外观模式
- 【LeetCode】 203. Remove Linked List Elements
- 【笔记整理】我们仍未知道那天所用的虚函数的原理
- 【3-1-29】mallocfree实战
- Py第十六问 ImportError: DLL load failed: %1 is not a valid Win32 application
- TCP BBR及MPTCP的一些想法
- 欢迎使用CSDN-markdown编辑器
- Unity3d 使用Texturepacker制作NGUI图集
- chrome本地保存账号密码获取思路
- Hadoop中自定义排序,分区,分组
- 排序算法学习