C++分析——多态与虚函数 virtual
来源:互联网 发布:shopee123软件怎么样 编辑:程序博客网 时间:2024/06/07 12:48
- C 虚函数的继承关系
- 基类Test_virtual_A
- 派生类Test_virtual_B
- 派生类Test_virtual_C
- 实现函数
- Test_virtual_A类自己调用
- Test_virtual_A类派生Test_virtual_B类
- Test_virtual_A类派生Test_virtual_C类
- Test_virtual_B类派生Test_virtual_C类
- 析构虚函数
- 纯虚函数
- 带有纯虚函数的基类Test_virtual_A
- 派生类Test_virtual_B
- 派生类Test_virtual_C
- 实现函数
- Test_virtual_A类为指针指向Test_virtual_B类
- Test_virtual_A类派生Test_virtual_C类
- Test_virtual_B类为指针指向Test_virtual_C类
- Test_virtual_C类自己创建对象
在类的函数前面加上 virtual即为虚函数,当基类的函数加上virtual时,表示该函数为虚函数,当子类对父类进行继承的时候,可以直接利用父类的虚函数的方法,也可以自己重新编写该函数的方法。
C++ 虚函数的继承关系
只有在父类的函数定义成为了虚函数后,子类才可以对该函数的功能进行改写,如同同类里的重载一样,不过不需要有传参类型不同的限制。没有加虚函数符号的函数只能使用父类现有的方法。
虚函数的源码示例
基类:Test_virtual_A
class Test_virtual_A{public: Test_virtual_A() { std::cout << __func__ << " Init " << std::endl; } virtual ~Test_virtual_A() { std::cout << __func__ << " close" << std::endl; } void Test_func1() { std::cout << "Test_virtual_A " << __func__ << std::endl; } virtual void Test_func2() { std::cout << "Test_virtual_A " << __func__ << std::endl; } void Test_func3() { std::cout << "Test_virtual_A " << __func__ << std::endl; } void Test_func4() { std::cout << "Test_virtual_A " << __func__ << std::endl; } };
派生类Test_virtual_B
class Test_virtual_B : public Test_virtual_A{public: Test_virtual_B() { std::cout << __func__ << " Init " << std::endl; } ~Test_virtual_B() { std::cout << __func__ << " close" << std::endl; } void Test_func1() { std::cout << "Test_virtual_B " << __func__ << std::endl; } void Test_func2() { std::cout << "Test_virtual_B " << __func__ << std::endl; } virtual void Test_func3() { std::cout << "Test_virtual_B " << __func__ << std::endl; } };
派生类Test_virtual_C
class Test_virtual_C : public Test_virtual_B{public: Test_virtual_C() { std::cout << __func__ << " Init " << std::endl; } ~Test_virtual_C() { std::cout << __func__ << " close" << std::endl; } void Test_func1() { std::cout << "Test_virtual_C " << __func__ << std::endl; } void Test_func2() { std::cout << "Test_virtual_C " << __func__ << std::endl; }};
实现函数
Test_virtual_A类自己调用
Test_virtual_A *p = new Test_virtual_A; p->Test_func1(); p->Test_func2(); p->Test_func3(); p->Test_func4(); delete p; p = NULL;
执行结果
Test_virtual_A Init Test_virtual_A Test_func1Test_virtual_A Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A close
Test_virtual_A类派生Test_virtual_B类、
Test_virtual_A *sp = new Test_virtual_B; sp->Test_func1(); sp->Test_func2(); sp->Test_func3(); sp->Test_func4(); delete sp; sp = NULL;
执行结果
Test_virtual_A Init Test_virtual_B Init Test_virtual_A Test_func1Test_virtual_B Test_func2 //虚函数体现Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_B close~Test_virtual_A close
对于来Test_virtual_B类说,自己virtual void Test_func3()声明为虚函数,但在其继承的父类Test_virtual_A中不是虚函数,因此只能使用父类Test_virtual_A的方法。
Test_virtual_A类派生Test_virtual_C类
Test_virtual_A *rp = new Test_virtual_C; rp->Test_func1(); rp->Test_func2(); rp->Test_func3(); rp->Test_func4(); delete rp; rp = NULL;
执行结果
Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_A Test_func1Test_virtual_C Test_func2 //虚函数体现Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close
Test_virtual_B类派生Test_virtual_C类
Test_virtual_B *tp = new Test_virtual_C; tp->Test_func1(); tp->Test_func2(); tp->Test_func3(); tp->Test_func4(); delete tp; tp = NULL;
执行结果
Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_B Test_func1Test_virtual_C Test_func2 //虚函数体现Test_virtual_B Test_func3 //虚函数体现Test_virtual_A Test_func4~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close
在基类Test_virtual_A中,只有函数virtual void Test_func2()被定义为虚函数,继承的类Test_virtual_B中,函数Test_func2没有定义虚函数的符号,但Test_virtual_B派生出的Test_virtual_C的Test_func2函数却实现了虚函数的特点,因此基类声明的虚函数,即使不再使用virtual虚函数关键字修饰该函数,在其派生类中也是虚函数。虚函数有多重继承的关系。 由于虚函数具有多重继承的关系,虽然可以在派生类中间定义虚函数,但会打乱函数的关联性,因此尽量在基类就订好哪个函数是虚函数,为后面的派生类进行规划。
析构虚函数
在上一节的Test_virtual_A中,虚构函数也被定义为虚函数virtual ~Test_virtual_A(),若没有定义为虚函数,那么上面的运行就会变成以下结果。
$ ./project.o Test_virtual_A Init Test_virtual_A Test_func1Test_virtual_A Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A closeTest_virtual_A Init Test_virtual_B Init Test_virtual_A Test_func1Test_virtual_B Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A close // Test_virtual_A类派生Test_virtual_B类Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_A Test_func1Test_virtual_C Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A close //Test_virtual_A类派生Test_virtual_B类Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_B Test_func3Test_virtual_A Test_func4~Test_virtual_B close //Test_virtual_A类派生Test_virtual_B类~Test_virtual_A close$
类结束后没有调用自身的析构函数,而是只调用了继承的父类的析构函数,所以需要在析构函数中加上virtual。
纯虚函数
父类定义的虚函数还可以有自己的实现方法,但如果定义为纯虚函数,则将方法去掉,只定义方法的接口,方法的实现完全由所派生的子类去实现,因此其本身不能被直接调用,只能被继承,本身作为一个接口规范去派生子类。因此在写纯虚函数的基类的时候尽量将所有的方法都写成纯虚函数,纯粹作为一个接口的定义标准。
修改上一节的Test_virtual_A类,将Test_func1定义为虚函数,虚函数写法:
virtual void Test_func1() = 0;
基类函数Test_virtual_A如下所示,与上一节不同的是,这个类添加了带参数的构造函数。
带有纯虚函数的基类Test_virtual_A
class Test_virtual_A{public: Test_virtual_A() { std::cout << __func__ << " Init " << std::endl; } Test_virtual_A(int a,int b) { std::cout << __func__ << " Init a = " << a << " b = " << b << std::endl; } virtual ~Test_virtual_A() { std::cout << __func__ << " close" << std::endl; } virtual void Test_func1() = 0; virtual void Test_func2() { std::cout << "Test_virtual_A " << __func__ << std::endl; } void Test_func3() { std::cout << "Test_virtual_A " << __func__ << std::endl; } void Test_func4() { std::cout << "Test_virtual_A " << __func__ << std::endl; } };
派生类Test_virtual_B
这个类有两个继承
class Test_virtual_B : public Test_virtual_A,public Test_inline{public: Test_virtual_B():Test_virtual_A(3,5),Test_inline(6,7) { std::cout << __func__ << " Init " << std::endl; } Test_virtual_B(int a,int b):Test_virtual_A(a,b),Test_inline(a,b) { std::cout << __func__ << " Init a = " << a << " b = " << b << std::endl; } ~Test_virtual_B() { std::cout << __func__ << " close" << std::endl; } void Test_func1() { std::cout << "Test_virtual_B " << __func__ << std::endl; } void Test_func2() { std::cout << "Test_virtual_B " << __func__ << std::endl; } virtual void Test_func3() { std::cout << "Test_virtual_B " << __func__ << std::endl; } };
派生类Test_virtual_C
与上一节不同的是,这次去掉对Test_func1的重载。
class Test_virtual_C : public Test_virtual_B{public: Test_virtual_C():Test_virtual_B(5,6) { std::cout << __func__ << " Init " << std::endl; } Test_virtual_C(int a,int b):Test_virtual_B(a,b) { std::cout << __func__ << " Init a = " << a << " b = " << b << std::endl; } ~Test_virtual_C() { std::cout << __func__ << " close" << std::endl; } void Test_func2() { std::cout << "Test_virtual_C " << __func__ << std::endl; }};
实现函数
Test_virtual_A类为指针指向Test_virtual_B类。
Test_virtual_A *sp = new Test_virtual_B(15,36); sp->Test_func1(); sp->Test_func2(); sp->Test_func3(); sp->Test_func4(); delete sp; sp = NULL;
执行结果
$ ./project.o Test_virtual_A Init a = 15 b = 36Test_virtual_B Init a = 15 b = 36Test_virtual_B Test_func1Test_virtual_B Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_B close~Test_virtual_A close$
Test_virtual_A类派生Test_virtual_C类。
Test_virtual_A *rp = new Test_virtual_C; rp->Test_func1(); rp->Test_func2(); rp->Test_func3(); rp->Test_func4(); delete rp; rp = NULL;
执行结果
$ ./project.o Test_virtual_A Init a = 5 b = 6Test_virtual_B Init a = 5 b = 6Test_virtual_C Init Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close$
Test_virtual_B类为指针指向Test_virtual_C类
Test_virtual_B *tp = new Test_virtual_C(49,68); tp->Test_func1(); tp->Test_func2(); tp->Test_func3(); tp->Test_func4(); cout << "Max is " << tp->Max() << endl;cout << "Min is " << tp->Min() << endl; delete tp; tp = NULL;
执行结果
$ ./project.o Test_virtual_A Init a = 49 b = 68Test_virtual_B Init a = 49 b = 68Test_virtual_C Init a = 49 b = 68Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_B Test_func3Test_virtual_A Test_func4Max is 68Min is 49~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close$
Test_virtual_C类自己创建对象
Test_virtual_C *cp = new Test_virtual_C(57,98); cp->Test_func1(); cp->Test_func2(); cp->Test_func3(); cp->Test_func4(); cout << "Max is " << cp->Max() << endl; cout << "Min is " << cp->Min() << endl; delete cp; cp = NULL;
执行结果
$ ./project.o Test_virtual_A Init a = 57 b = 98Test_virtual_B Init a = 57 b = 98Test_virtual_C Init a = 57 b = 98Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_B Test_func3Test_virtual_A Test_func4Max is 98Min is 57~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close$
- C++分析——多态与虚函数 virtual
- 黑马程序员——虚函数virtual与重写override实现多态
- 学习整理——C++ virtual虚函数与多态
- C++——中的虚函数(Virtual function)
- 虚函数——virtual
- 虚函数(virtual function),实现多态
- virtual与多态
- C#:study(6)--多态与virtual、abstract
- 【C++】析构函数和virtual函数引发的隐晦问题 ——《Effective C++》
- 虚函数(virtual)与多态(polymorphism)、动态绑定(dynamic binding)
- virtual 函数与纯virtual函数
- 与虚函数相关的几点注意之一——virtual的向后传递
- abstract抽象与virtual虚函数
- c# 虚函数Virtual与重写override
- static 与virtual函数
- C#---virtual与abstract
- 构函数virtual与非virtual区别
- virtual关键字与多态
- hdoj 2063 过山车
- 子序列的和
- 试用了阿里云市场的验证码识别api,真的牛批,传统4位数验证码识别率超高
- 选课-二叉2
- 多重背包的优化 二进制/单调队列解析
- C++分析——多态与虚函数 virtual
- EIGRP协议
- GUID大全
- kvm-qemu 基本功能介绍(一)
- Codeforces Round #442 (Div. 2)-E-Danil and a Part-time Job(DFS序+线段树区间更新)
- LeetCode594. Longest Harmonious Subsequence
- codeforces 731A【python】
- VK Cup 2017
- C++库函数sort简要示例