Probe into the problems related to virtual function
This article explores the virtual function in five ways.
1) virtual function single Inheritance object model.
2) Virtual table pointer and virtual table creation release time.
3) destructors are set to virtual functions.
4) The constructor calls the virtual function.
5) destructor call virtual function.
1. Virtual function single Inheritance object model
See website: http://www.cnblogs.com/taoxu0903/archive/2008/02/04/1064234.html.
Reference book: "C + + object Model".
virtual function Implementation mechanism: using late binding mechanism. class contains virtual table pointer member variables, virtual table pointers execute virtual function address tables.
Detection code:
class Base{public: virtualvoidx(); virtualvoid y();private: intpublic Base{public: voidx(); virtualvoid z();private: long lval;};
The corresponding Memory object model is as follows.
2. Creation of virtual table pointers and virtual tables release time
Conclusion: Virtual tables and virtual table pointers are created at the time of constructor, and are disposed in destructors.
Let's track the creation and release time.
Code:
#include "stdafx.h"#include <iostream>using namespace STD;classbase{ Public: Base () { This; }Virtual voidPrint () {}Virtual~base () { This; }};classDerived: Publicbase{ Public: Derived () { This; }Virtual voidPrint () {} ~derived () { This; }};int_tmain (intARGC, _tchar* argv[]) {base* PB =NewDerived ();DeletePB; PB = NULL;return 0;}
The breakpoint Trace virtual table pointer process is as follows.
1) base::base ()
Initializes a base class virtual table with a virtual table pointer pointing to the base class virtual table 0x00de7840.
2) Derived::D erived ()
Initializes the derived class virtual table, and the virtual table pointer points to the derived class virtual table 0x00de7834.
3) derived::~derived ()
Frees the derived class virtual table, and the virtual table pointer points to the base class virtual table 0x00de7840.
4) Base::~base ()
Frees the base class virtual table and releases the virtual table pointer.
3. destructor set to virtual function
First, the conclusion: if the destructor is not set to a virtual function, there is a danger that the virtual function of the inheriting class will not be invoked.
Recommendation: Destructors are set to virtual functions.
Detection code:
classbase{ Public: Base () {cout<<"Base"<<endl; } ~base () {cout<<"~base"<<endl; }};classDerived: Publicbase{ Public: Derived () {cout<<"Derived"<<endl; } ~derived () {cout<<"~derived"<<endl; }};int_tmain (intARGC, _tchar* argv[]) {base* PB =NewDerived ();DeletePB;return 0;}
Output Result:
Base
Derived
~base
You can see that the destructor of the inheriting class is not called.
Set the destructor of the base to a virtual function
virtual ~Base(){ cout<<"~Base"<<endl;}
The output is normal:
Base
Derived
~derived
~base
4. Constructor call virtual function
Question: Can a virtual function be called in a constructor?
Answer: You can call, but not the behavior we expect, to call a virtual function just the function of the current class.
Recommendation: Try not to call virtual functions in the constructor.
See C + + Proverbs: Avoid calling virtual functions in constructs or destructors.
Code:
#include "stdafx.h"#include <iostream>using namespace STD;classbase{ Public: Base () {cout<<"Base"<<endl; Print (); }Virtual voidPrint () {cout<<"Base::P rint ()"<<endl; }Virtual~base () {cout<<"~base"<<endl; }};classDerived: Publicbase{ Public: Derived () {cout<<"Derived"<<endl; Print (); }Virtual voidPrint () {cout<<"Derived::P rint ()"<<endl; } ~derived () {cout<<"~derived"<<endl; }};int_tmain (intARGC, _tchar* argv[]) {base* PB =NewDerived ();DeletePB;return 0;}
Output Result:
Base
Base::P rint ()
Derived
Derived::P rint ()
~derived
~base
Analysis: When a constructor calls a virtual function, the virtual table pointer points to the base class virtual table, so the constructor calls the virtual function to call the base class function.
5. destructor Call virtual function
Question: Can a virtual function be called in a destructor?
Answer: You can call, but not the behavior we expect, to call a virtual function just the function of the current class.
Recommendation: Try not to call virtual functions in destructors.
Code:
#include "stdafx.h"#include <iostream>using namespace STD;classbase{ Public: Base () {cout<<"Base"<<endl; }Virtual voidPrint () {cout<<"Base::P rint ()"<<endl; }Virtual~base () {Print ();cout<<"~base"<<endl; }};classDerived: Publicbase{ Public: Derived () {cout<<"Derived"<<endl; }Virtual voidPrint () {cout<<"Derived::P rint ()"<<endl; } ~derived () {Print ();cout<<"~derived"<<endl; }};int_tmain (intARGC, _tchar* argv[]) {base* PB =NewDerived ();DeletePB;return 0;}
Output Result:
Base
Derived
Derived::P rint ()
~derived
Base::P rint ()
~base
Analysis: When a derived class is destructor-executed, the virtual table pointer points to the base-class virtual table, so the virtual function in the base class is called to the function of the base class instead of the derived class.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Probe into the problems related to virtual function