Everyone is familiar with virtual tables. We all know that every class object containing virtual functions has a virtual pointer, but in actual use, it is always due to this and debugging for half a day, it turns out that it was a virtual pointer. I have also tried it during code Debugging Over the past few days. My problem is this. For example, CTree is the underlying base class (non-virtual class) and CSamplerTree (Virtual class) derived from CTree, CMSamplerTree, and CASamplerTree,
CTree includes two member variables: QList <CTree *> childList; Number of child nodes in the tree; CTree * parent; Father's Day of the current Tree node, in the program, I use a lot of CTree * pTree pointers to CSamplerTree, CMSamplerTree, and CASamplerTree to achieve unified processing, so that the code is concise and highly reusable. But who once thought that the program would crash as soon as it was run. Through debugging, we found that when CSamplerTree, CMSamplerTree, and CASamplerTree pointers point to the CTree pointer, the address is added with 4. Why? To deepen my understanding, I made a simple test code:
[Cpp]
# Include <stdio. h> class CBase {
Public:
CBase (){}
Void func ()
{
Printf ("base \ n ");
}
};
Class CDerived: public CBase {
Public:
CDerived (){}
Virtual void func1 ()
{
Printf ("derived \ n ");
}
};
Void main ()
{
CBase * pBase = new CDerived ();
PBase-> func ();
CDerived * pDerived = (CDerived *) pBase;
Printf ("% d \ n", pDerived, pBase );
PDerived-> func ();
CBase * pBase1 = new CBase ();
PBase1-> func ();
CDerived * pDerived1 = (CDerived *) pBase1;
Printf ("% d \ n", pDerived1, pBase1 );
PDerived1-> func ();
}
# Include <stdio. h> class CBase {
Public:
CBase (){}
Void func ()
{
Printf ("base \ n ");
}
};
Class CDerived: public CBase {
Public:
CDerived (){}
Virtual void func1 ()
{
Printf ("derived \ n ");
}
};
Void main ()
{
CBase * pBase = new CDerived ();
PBase-> func ();
CDerived * pDerived = (CDerived *) pBase;
Printf ("% d \ n", pDerived, pBase );
PDerived-> func ();
CBase * pBase1 = new CBase ();
PBase1-> func ();
CDerived * pDerived1 = (CDerived *) pBase1;
Printf ("% d \ n", pDerived1, pBase1 );
PDerived1-> func ();
} The following is the output result. The result shows that the pointer of the derived class is directed to the base class pointer, And the pointer address is 4. When the base class Pointer Points to the base class, the pointer address is reduced by 4.
Base
200672 200676
Derived
Base
200740 200744
Press any key to continue
Next we will look at how the memory of the derived class object and the base class object are organized. We will introduce two variables based on the above example. The Code is as follows:
[Cpp]
# Include <stdio. h> class CBase {
Public:
CBase (){}
Void func ()
{
Printf ("base \ n ");
}
Int;
};
Class CDerived: public CBase {
Public:
CDerived (){}
Virtual void func1 ()
{
Printf ("derived \ n ");
}
Int B;
};
Void main ()
{
CBase * pBase = new CDerived ();
CDerived * pDerived = (CDerived *) pBase;
Printf ("% d \ n", pDerived, pBase );
Printf ("% d \ n", & pDerived-> a, & pDerived-> B, & pBase-> );
}
# Include <stdio. h> class CBase {
Public:
CBase (){}
Void func ()
{
Printf ("base \ n ");
}
Int;
};
Class CDerived: public CBase {
Public:
CDerived (){}
Virtual void func1 ()
{
Printf ("derived \ n ");
}
Int B;
};
Void main ()
{
CBase * pBase = new CDerived ();
CDerived * pDerived = (CDerived *) pBase;
Printf ("% d \ n", pDerived, pBase );
Printf ("% d \ n", & pDerived-> a, & pDerived-> B, & pBase-> );
}
200672 200676
200676 200680 200676
Press any key to continue
From the output, we can see that the starting address of the CDerived object is the virtual table pointer vptr, followed by the member variables of the base class, followed by its own member variables.