c++中的虚函数与纯虚函数
来源:互联网 发布:女士西装套裙知乎 编辑:程序博客网 时间:2024/05/22 00:54
虚函数是C++很重要的一部分,C++的多态就是靠它完成的
首先怎么让一个函数成为虚函数
很简单,在函数声明前面加上 virtual 就可以了。如:
class BaseClass{public:virtual void Func()//虚函数{printf("Func In BaseClass\n");}};
然后我们看看虚函数究竟有什么特别之处
假设我们通过继承得到一个子类:
class ChildClass1 : public BaseClass{public:void Func(){printf("Func In ChildClass\n");}};
然后再在main函数输入测试代码:
int main(){ChildClass1 child;BaseClass* pClass = &child;pClass->Func(); return 0;}
看看结果:
明明是BaseClass* 类型的 pClass调用的居然是ChildClass1类的方法
当然你可能认为正很正常,毕竟你是把 ChildClass1 类型的child 的地址复制给了pClass
但如果Func不是虚函数呢?
#include <stdio.h>class BaseClass{public:void Func() //注意:现在Func不是虚函数{printf("Func In BaseClass\n");}};class ChildClass1 : public BaseClass{public:void Func(){printf("Func In ChildClass\n");}};int main(){ChildClass1 child;BaseClass* pClass = &child;pClass->Func(); return 0;}
结果却是
之后我们来看看虚函数的用处
1.将析构函数声明为虚函数
#include <stdio.h>class BaseClass{public:virtual ~BaseClass()//析构函数是虚函数{printf("Func In BaseClass\n");}};class ChildClass1 : public BaseClass{public:~ChildClass1(){printf("Func In ChildClass\n");}};int main(){ChildClass1* child = new ChildClass1();BaseClass* pClass = child;delete pClass; return 0;}
我们会的到结果:
看我们 delete 掉 BaseClass* 类型的 pClass ,因为 pClass 的值是由 ChildClass1* 类型的 child 复制得到的,所以会调用ChildClass1的析构函数(就是说他不只调用了父类的析构函数,也会调用子类的析构函数)
如果不是虚函数呢?
#include <stdio.h>class BaseClass{public:~BaseClass() //注意:现在不是虚函数{printf("Func In BaseClass\n");}};class ChildClass1 : public BaseClass{public:~ChildClass1(){printf("Func In ChildClass\n");}};int main(){ChildClass1* child = new ChildClass1();BaseClass* pClass = child;delete pClass; return 0;}
结果只调用了父类的析构函数
有时候我们会在子类里new一些变量出来,很多时候都是在子类的析构函数里才把他们delete掉。
而如果你new一个这样的子类出来,然后将它转型为父类指针delete掉,就需要将基类的析构函数声明为虚函数。
(就像我等下说的学校职工管理系统的例子,就需要用delete基类指针的方式释放new出来的子类)
2.我们可以用一个父类指针数组管理多个不同的子类(当然,实际编程中多数用vector容器)
#include <stdio.h>class BaseClass{public:virtual ~BaseClass() {printf("~BaseClass\n");}virtual void Func(){printf("Func In BaseClass\n");}};class ChildClass1 : public BaseClass{public:~ChildClass1(){printf("~ChildClass1\n");}void Func(){printf("Func In ChildClass1\n");}};class ChildClass2 : public BaseClass{public:~ChildClass2(){printf("~ChildClass2\n");}void Func(){printf("Func In ChildClass2\n");}};int main(){BaseClass* classGroup[2];classGroup[0] = new ChildClass1();classGroup[1] = new ChildClass2();for(int i = 0; i<2 ; i++)classGroup[i]->Func();for(int j = 0; j<2 ; j++)delete classGroup[j];return 0;}结果得到:
也就是说,当我们有很多个不同的子类需要统一管理的时候,虚函数就有了大用处。
具体的例子就是你为学校写了个职工管理系统,尽管学校里面的职工有很多种(老师、保安、清洁员、饭堂阿姨......)你每一种写了一个类,但都继承于Employee这个类
class Employee { public: //干活, “=0“ 是纯虚函数的意思,我等下讲 virtual Work() = 0; //拿工资 virtual GetSalary() = 0; }; class 老师类 : public Employee{...};class 保安类 : public Employee{...};class 保洁员类 : public Employee{...};
于是你就只需要来一个 Employee数组 或者 Employee vector容器,每多一个职工就对应着new出一个具体的子类实例。将所有不同的子类实例都放进去,然后来一个循环让他们干活,再来一个循环然他们拿工资
你可以这样做:
std::vector<Employee*> group;Employee* pNewEmployee;//新来一个老师pNewEmployee = new 老师类();group.push_back(pNewEmployee);//新来一个保安pNewEmployee = new 保安类();group.push_back(pNewEmployee);//新来一个保洁员pNewEmployee = new 保洁员类();group.push_back(pNewEmployee);至于循环那里我就不说了,自己可以想想
最后讲讲纯虚函数
纯虚函数就是一种特殊的虚函数,它拥有虚函数的所用功能(当然也有不同于虚函数的地方)
我们这样将一个函数声明为纯虚函数:
class AClass{public:virtual void Func() = 0;};(也就是虚函数后面多一个 ” = 0 “而已)
如果一个类中有纯虚函数,那么这个类就不能被实例化
也就是:
class AClass{public:virtual void Func() = 0;};int main(){//会报错,编译不通过AClass a; //也会报错,编译不通过AClass* b = new AClass(); return 0;}
必须有一个子类实现他的纯虚函数,才能被实例化
class AClass{public:virtual void Func() = 0;};class ChildClass :public AClass{public:void Func() {}};int main(){//会报错,编译不通过//AClass a; //也会报错,编译不通过//AClass* b = new AClass(); //这样才能编译通过ChildClass a; ChildClass* b = new ChildClass(); return 0;}
值得一提的是子类必须实现父类的所有纯虚函数才能被实例化
class AClass{public:virtual void Func() = 0;};class ChildClass :public AClass{public:void Func(); //如果只有声明而没有实现它};int main(){//编译不通过ChildClass a; ChildClass* b = new ChildClass(); return 0;}
class AClass{public:virtual void Func() = 0;};class ChildClass :public AClass{public://或者你连声明都没有。。。};int main(){//编译不通过ChildClass a; ChildClass* b = new ChildClass(); return 0;}
PS:本人喜欢用 printf 多于 cout(因为现在学c++都不怎么打控制台程序了,C语言时打习惯了printf......)
- [C++]虚函数与纯虚函数
- c++-虚函数与纯虚函数
- C++、JAVA与C#中的多态虚函数、纯虚函数(抽象函数)
- C++、JAVA与C#中的多态虚函数、纯虚函数(抽象函数)
- C++、JAVA与C#中的多态虚函数、纯虚函数(抽象函数)
- C++:纯虚函数与抽象类
- 【C/C++】纯虚函数
- 二、C++ 中的 虚函数与纯虚函数
- c++中的虚函数与纯虚函数
- C++——虚函数与纯虚函数
- C++中的纯虚函数
- C++中的纯虚函数
- C++中的纯虚函数
- c++ 中的纯虚函数
- C++中的纯虚函数
- C++中的纯虚函数
- C++中的虚函数、纯虚函数
- C++: 浅谈虚函数、纯虚函数
- iOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem
- 博客开始写,博客园有个bug
- Windows核心编程(二十)模块的基地址重定位及绑定
- Android SQLite 经验分享
- 成龙太庙跨汗血宝马
- c++中的虚函数与纯虚函数
- Leetcode_set-matrix-zeroes
- jquery学习笔记-问题积累1
- 高中生活与古希腊世界 ---节选自社会动物
- hdu-Cube(三位树状数组)
- JAVA和JS常用函数对比
- iOS学习之UINavigationController详解与使用(二)页面切换和segmentedController
- hdu2187悼念512汶川大地震遇难同胞——老人是真饿了
- 关于android的4.2的0文件夹的详解