Data Member of the category of virtual functions and common member functions

Source: Internet
Author: User

Data Member of the functions class of virtual functions and common member functions:

Class

{

Protected:

Int m_data;

Public:

A (int data = 0) {m_data = data ;}

Int getdata () {return dogetdata ();}

Virtual int dogetdata () {return m_data;/* m_data = 0 */}

};

 

Class B: public

{

Protected:

Int m_data;

Public:

B (INT DATA = 1) {m_data = data ;}

// M_data = 0 in a and m_data = 1 in B

 

Int dogetdata () {return m_data;/* m_data = 1 * // implementation Interface

};

 

Class C: Public B

// C inherits the methods and attributes of Class A and Class B, and does not define new interfaces. Therefore, the interfaces are defined in Class B.

{

Protected:

Int m_data;

Public:

C (int data = 2) {m_data = data ;}

// M_data = 0 in a, m_data = 1 in B, and m_data = 2 in C

};

 

Int main ()

{

C (10 );

Cout <C. getdata () <Endl; // The output is: 1

Cout <C. A: getdata () <Endl; // The output is: 1

Cout <C. B: getdata () <Endl; // The output is: 1

Cout <C. C: getdata () <Endl; // The output is: 1

 

Cout <C. dogetdata () <Endl; // The output is: 1

Cout <C. A: dogetdata () <Endl; // The output is: 0.

Cout <C. B: dogetdata () <Endl; // The output is: 1

Cout <C. C: dogetdata () <Endl; // The output is: 1

 

System ("pause ");

Return 0;

}

Analysis: getdata () is a common member function, and dogetdata () is a virtual function. In addition, like a common member function, a virtual function must add the this pointer to the final call,

For example

Int dogetdata () {return m_data;} Actually after adding the this pointer, it is actually:

Virtual int dogetdata (A * const this) {return this-> m_data ;},

If you are not used to the parameter this, you can replace it with another parameter:

Virtual int dogetdata (A * const Pa) {return pa-> m_data;}--(Code 1)

 

The common member function getdata () of Class A also has the this pointer, that is,

Int getdata () {return dogetdata ();} is actually:

Int getdata (A * const Pa) {return
Pa-> dogetdata ();}---(Code 2)

// Note that Pa-> dogetdata () executes virtual functions with polymorphism.

 

(1) c. getdata (): If the class C does not define getdata (), the getdata () of the parent class B is called, and the getdata () of the parent class B is also not defined. Therefore, the getdata () of the grandfather Class A is called (), that is, getdata (A * const Pa), where pa points to the C Class Object C (actually equivalent to calling getdata (C * const PC), but since C does not define getdata (), therefore, if no getdata (C * const PC) exists, the getdata () of the parent class is called, that is, getdata (B * const Pb), which is also not defined in Class B, therefore, getdata () of the grandfather Class A is called, that is, getdata (
A * const Pa), that is, find the called function in the order of getdata (C * const PC), getdata (B * const Pb), and getdata (A * const PA ).

Then execute (Pa-> dogetdata () in Code 2). Since dogetdata () is a virtual function, execute dogetdata () in the virtual function table, that is, there will be polymorphism, that is, Calling C:: dogetdata (), while C: dogetdata () is not defined, so the dogetdata () of the parent class B is called, that is

Virtual int dogetdata (B * const Pb) {return Pb-> m_data;}--(Code 3)

PB points to Class C Object C.

That is, m_data in Class B is accessed, that is, 1.

Note: The virtual functions of the struct class are polymorphism, while the data members are not polymorphism, for example, (Code 3 ):

Virtual int dogetdata (B * const Pb) {return Pb-> m_data;}. Because Pb is of the B * type, no matter whether Pb actually points to the B object in the memory, or B's derived object (such as C), Pb-> m_data always accesses m_data in B class, that is, 1.

The virtual function is polymorphism because the function in the virtual function table has been overwritten by the function of the actual memory object. The data members do not have polymorphism because the data members access the memory range (such as a * P) of sizeof (pointer declaration type) starting from the pointer address; then p-> m_data is the range of access from P and the size is sizeof (a); While B * P; then p-> m_data is access from P, the size is in the range of sizeof (B ).

 

(2) c. a: getdata (): Because getdata () in A may be hidden, to access getdata () in A, C. a: getdata (). Note that C. a: In getdata (), A: Only the scope indicates that C calls the getdata () function of Class A. This points to C, that is, call getdata (A * const Pa ), the PA points to the C Class Object C. This is the same as (1), and the output is also 1.

Note: C. A: getdata () is called getdata (A * const Pa), where pa points to C Class Object C.

 

(3) c. b: getdata (): Call getdata () in B. This points to C, that is, call getdata (B * const Pb), where Pb points to C Class Object C. Because Class B does not overwrite getdata (), that is, call getdata () of Class A, that is, call getdata (A * const Pa), where pa points to Class C Object C, then execute (Code 2), which has the same effect as (1), and the output is still 1.

 

(4) C. C: getdata () is the same as (3.

 

(5) C. dogetdata (): Because C does not overwrite dogetdata (), execute B: dogetdata (), that is, actually call dogetdata (B * const Pb ), PB points to Class C Object C, that is, execution (Code 3), and accesses m_data in Class B, that is, 1.

(6) C. a: dogetdata (): Call dogetdata () of Class A. This points to C, that is, call dogetdata (A * const Pa), where pa points to C Class Object C, that is, execution (Code 1), that is, accessing m_data of Class A, that is, 0.

 

(7) C. B: dogetdata () and (8) C. C: dogetdata () are the same.

 

In short, remember the following two points:

"1" common member functions and virtual functions add the this pointer to the parameter list. (See exploring the C ++ Object Model in depth p147)

2 virtual functions have polymorphism, while data members do not.

3 common member functions are based on the this pointer type (such as a *, B *, or C *), and virtual functions are based on the memory objects actually directed to the pointer.

 

Essence of virtual function call: M * p, p-> VF (). Locate the address P in the memory and call VF (N * const PN) in the virtual table pointed by the virtual table pointer at p ). For example, C; A * P = & C; P-> dogetdata () locates the address P in the memory and calls dogetdata (A * const PA ), pa is the starting address of C.

In fact, it is not so advanced. For a * P = & C, it is equivalent to knowing a object A0 (it actually belongs to Class C, but the compiler does not care whether it belongs to Class C or not, only use it as a common a object. Because P refers to an object of the type, the P operation can only access the range of sizeof (m) starting from P ), when you want to access a data member, you can find the data member based on the offset relative to the memory address p. If you have a virtual function (VF (), search for VF () in the virtual table pointer _ vfptr pointing to in P memory and call it.

 

You do not need to use this to view the results quickly. If it is a common member function, it depends on the class in which the function is accessed and the data member of the class. If it is a virtual function, it accesses the virtual function that actually points to the memory object.

 

 

――――――――――――――――――――――――

Appendix:

Code:

Class M

{

Public:

M (): M_c (300), m_d (400), m_ch (
'A'), m_ch2 ('B '){}

Void fun ()

{

Int I = m_d;

Char CH = m_ch2;

}

Int M_c;

Int m_d;

Char m_ch;

Char m_ch2;

};

The disassembly of the fun () function is as follows:

Void fun ()

{

01271580 push EBP

01271581 mov EBP, ESP

01271583 sub ESP, 0e4h

01271589 push EBX

010000158a push ESI

010000158b push EDI

010000158c push ECx

010000158d Lea EDI, [ebp-0E4h]

01271593 mov ECx, 39 h

01271598 mov eax, 0 cccccccch

010000159d rep STOs dword ptr es: [EDI]

010000159f pop ECx

01000015a0 mov dword ptr [ebp-8], ECx

Int I = m_d;

01000015a3 mov eax, dword ptr [this]

01000015a6 mov ECx, dword ptr [eax + 4]

01000015a9 mov dword ptr [I], ECx

Char CH = m_ch2;

01000015ac mov eax, dword ptr [this]

01000015af mov Cl, byte PTR [eax + 9]

01000015b2 mov byte PTR [CH], Cl

}

01000015b5 pop EDI

01000015b6 pop ESI

01000015b7 pop EBX

01000015b8 mov ESP, EBP

01000015ba pop EBP

01000015bb RET

The data member alignment in the class is as follows:

M_c

M_d

M_ch m_ch2 __

 

The class access data member is added with the offset of the data member at the beginning (that is, this) of the current class object. For example, if the this pointer address is set to XXX, M_c address is (xxx + 0), m_d address is (xxx + 4), m_ch address is (xxx + 8 ), m_ch2 address: (xxx + 9 ).

 

(1) When converting the object pointers of two classes, if the two classes have an inheritance relationship, there is a certain offset after the conversion. For example, Class A {int I ;}; Class B {int K}; Class C: Public A, public B {};

For C * Pc = new C; // set Pc = xxx

B * pb = pc; // The offset of Part B relative to the start point of C is 4, Pb = xxx + 4.

As shown in:

(2) If the two classes do not have an inheritance relationship, there is no offset after the conversion:

Class

{

Public:

A (): M_a (100), m_ B (200 ){}

Void print ()

{

Cout <"A: Print ()" <Endl;

}

Int M_a;

Int m_ B;

};

Class C

{

Public:

C (): M_c (300), m_d (400), m_e (500 ){}

Void print ()

{

Cout <m_d <Endl;

}

Int M_c;

Int m_d;

Int m_e;

 

};

Void main ()

{

A;

A * pA = & A; // set Pa = xxx

C * Pc = (C *) (& A); // Pc = xxx, no offset.

PC-> Print ();

/* 200 output. Access m_d in C. Because m_d is offset 4 from the starting address of class C in Class C, it is equivalent to the int value starting from 4th bytes of XXX, that is, the int value of access (xxx + 4). Because the value at (xxx + 4) is assigned a: m_ B value of 200, m_d = 200 instead of 400. */

 

System ("pause ");

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.