C + + class size (including virtual function) __ function

Source: Internet
Author: User
Tags int size modifier visibility

Although it is difficult to find a C + + book or magazine that does not discuss polymorphism, most of these discussions make it difficult to use polymorphism and C + + virtual functions. In this article, I intend to make the reader understand the virtual function implementation technology in C + + from several aspects and combine some examples. To illustrate, write this article just want to exchange learning experience with you because I have a shallow knowledge, there are some mistakes and deficiencies, I hope everyone criticized and corrected, in this deep thank you.

in a class, if there is nothing, the class occupies 1 bytes, and once the class has other space-occupying members, the 1 bytes are not counted, as a class with only one int occupies 4 bytes instead of 5 bytes.

if only a member function, or only 1 bytes, because the class function does not occupy space

virtual function Because there is a virtual function table, requires 4 bytes, data member objects if the pointer is 4 bytes, note that there is byte alignment, if 13 bytes, then carry to 16 bytes of space.

I. Basic CONCEPTS
First, C + + realizes polymorphism through virtual functions. " Regardless of the class in which the message is sent, they send a message with the same form, and the handling of the message may change with the object of the takeover message "The way it is called polymorphism." "In the hierarchy of a class built on a base class, you can invoke a procedure of the same name in the object of any derived class, and the process provided by the invoked procedure can change with the class to which it belongs. The virtual function is first a member function that can be redefined in the derived class of the class and given another processing function.

Definition of virtual function and redefinition in derived class

Class Name {
Public
Virtual member function description;
}

Class Name: base class Name {
Public
Virtual member function description;
}

Three, the structure of virtual function in memory

1. Let's take a look at an example:

#include "iostream.h"
#include "string.h"

Class A {
Public
virtual void Fun0 () {cout << "a::fun0" << Endl;}
};


int main (int argc, char* argv[])
{
A A;
cout << "Size of A =" << sizeof (a) << Endl;
return 0;
}
The result is as follows: Size of A = 4

2. If you add another virtual function: virtual void fun1 () {cout << "a::fun" << Endl;}
Get the same result. If you remove the virtual modifier in front of the function

Class A {
Public
void Fun0 () {cout << "a::fun0" << Endl;}
};


int main (int argc, char* argv[])
{
A A;
cout << "Size of A =" << sizeof (a) << Endl;
return 0;
}
The result is as follows: Size of A = 1

3. Looking at the following results:

Class A {
Public
virtual void Fun0 () {cout << "a::fun0" << Endl;}
int A;
int b;
};
int main (int argc, char* argv[])
{
A A;
cout << "Size of A =" << sizeof (a) << Endl;
return 0;
}
The result is as follows: Size of A = 12

In fact, virtual functions are structured in memory in this way:


Figure I

Under window2000 The pointer occupies 4 bytes in memory, and the virtual function saves the address of the function in a virtual function table (VTABLE). Look at the example below.

Class A {
Public
virtual void Fun0 () {cout << "a::fun0" << Endl;}
virtual void fun1 () {cout << "a::fun1" << Endl;}

};
int main (int argc, char* argv[])
{
A A;
cout << "Size of A =" << sizeof (a) << Endl;
return 0;
}

The results are as follows:
Size of A = 4

The memory structure of the virtual function is as follows, you can also through the function pointer, first find the virtual function table (VTABLE), and then access to each function address to verify the structure, in the foreign web site author is: Zeeshan Amjad wrote "ATL on the Hood" is described in detail.


Figure II

4. Let's take a look at the memory structure of the virtual function in the inheritance, first look at the following example

Class A {
Public
virtual void F () {}
};
Class B {
Public
virtual void F () {}
};
Class C {
Public
virtual void F () {}
};
Class Drive:public A, public B, public C {
};
int main () {
Drive D;
cout << "Size is =" << sizeof (d) << Endl;
return 0;
}
The results are as follows: the Size is = 12, I believe you will see the following structure diagram is very clear,


Figure Three

5. Let's take a look at a virtual function to achieve polymorphism, first look at an example:

Class A {
Public
virtual void F () {cout << "a::f" << Endl;}
};
Class B:p ublic a{
Public
virtual void F () {cout << "b::f" << Endl;}
};
Class C:p ublic A {
Public
virtual void F () {cout << "c::f" << Endl;}
};
Class Drive:public C {
Public
virtual void F () {cout << "d::f" << Endl;}
};

int main (int argc, char* argv[])
{
A A;
b b;
c C;
Drive D;
A.F ();
B.f ();
C.F ();
D.F ();
return 0;
}
Result: A::f
B::f
C::f
D::f

No need to explain, I believe everyone can see what the truth. Note: Polymorphism is not a function overload

6. Implementing a dynamic connection with virtual functions during compilation, the C + + compiler determines that the program uses that function, based on the arguments that the program passes to the function, or the function return type, and then the compiler replaces each startup with the correct function. This compiler-based substitution is called a static connection, and they are executed before the program is run. On the other hand, when a program executes polymorphism, the substitution occurs during the execution of the program, which is called a dynamic connection. The following example:

Class a{
Public
virtual void F () {cout << "a::f" << Endl;};
};

Class B:public a{
Public
virtual void F () {cout << "b::f" << Endl;};
};
Class C:public a{
Public
virtual void F () {cout << "c::f" << Endl;};
};
void Test (A *a) {
A->f ();
};
int main (int argc, char* argv[])
{
b *b=new B;
c *c=new C;
char choice;
do{
cout<< "type B for Class B,c for class C:" <<endl;
cin>>choice;
if (choice== ' B ')
Test (b);
else if (choice== ' C ')
Test (c);
}while (1);
cout<<endl<<endl;
return 0;
}

In the example above, if you remove the virtual modifier from the class a,b,c, look at the printed result, and then look at the following example to see the connection between the two. If you remove the virtual modifier in B and C, what happens, the result is the same as not being removed.

7. Call a function of an inherited class in the base class (if this function is a virtual function) or look at the example first:

Class A {
Public
virtual void fun () {
cout << "A::fun" << Endl;
}
void Show () {
Fun ();
}
};

Class B:public A {
Public
virtual void fun () {
cout << "B::fun" << Endl;
}
};

int main () {
A A;
A.show ();

return 0;
}
Print Results: A::fun

In the example in 6, test (a *a) actually has a process in which an inherited class pointer implicitly converts to a base-class pointer. We can see that using virtual functions we can invoke inherited class functions in the base class. However, if it is not a virtual function, the inheriting class pointer can only call the base class function after it has been converted to a base class pointer. Conversely, if the base class pointer transforms to an inherited class pointer, it can only be displayed and transformed, and the transformed inheriting class pointer may call the base class and the inheriting class pointer. The following example:

Class A {
Public
void Fun () {
cout << "A::fun" << Endl;
}

};
Class B:public A {
Public
void Fun () {
cout << "B::fun" << Endl;
}
void Fun0 () {
cout << "B::fun0" << Endl;
}
};
int main () {
A *a=new A;
b *b=new B;
A *pa;
B *PB;
Pb=static_cast<b *> (a); The base class pointer transforms the display of the inheriting class pointer
Pb->fun0 ();
Pb->fun ();
return 0;
}
Resources:

1. Science Press "C + + Programming"

2. Zeeshan Amjad ATL on the Hood


Supplement (I summarize):

Class CA
{
Public
CA (void);
virtual void f () {int a = 10;}
virtual void G () {}
Private
int C;
};

At this point sizeof (CA) equals 8;

Class CA
{
Public
CA (void);
virtual void f () {int a = 10;}
Private
int C;
};

At this point sizeof (CA) equals 8;


Class CA
{
Public
CA (void);
virtual void f () {int a = 10;}
Private
int C;

Char ch;
};

At this point sizeof (CA) equals 12;

Class CA
{
Public
CA (void);
virtual void f () {int a = 10;}
Private
int C;

Char ch1;

Char CH2
}; At this point sizeof (CA) equals 12;

Class CA
{
Public
CA (void);
virtual void f () {int a = 10;}
Private
int C;

Char ch1;

int D;

}; At this point sizeof (CA) equals 16;

because the distribution of classes also takes into account the mechanism of byte alignment


The static keyword in C + + inherits from the C language and contains two meanings: static storage and visibility control. Variables defined as static types are saved in the global data area, variables defined as static types, or functions can only be accessed within this compilation unit, so that a variable with the same name in a different file will not have a duplicate definition error. The application of static in C + + is divided into two aspects: one is for ordinary function and variable, the other is application in class.
The application of common functions and variables
1. Static Global variables
With the global variable preceded by static, the variable becomes a static global variable. Static global variables have the following characteristics:
1), the variable is stored in the global data area;
2), the variable will be automatically initialized to 0;
3. Static global variables are visible within the entire compilation unit (the entire file), but not outside the file.
The feature that the static variable is automatically initialized to 0 can bring some convenience to the development of the program, such as defining an array of strings to allow the character to end with '/0 ' to iterate through the entire array, but the array of strings defined as static is automatically populated with 0 '/ 0 ' is 0, so using these features can increase the operation efficiency of the program. Global variables that need to be shared within the current compilation unit can be set to static so that they do not have to worry about having duplicate names in other files to meet the requirements.
The following code shows the characteristics of a static global variable:
View plain Copy to clipboard print?
File1.cpp
#include <iostream>
using namespace Std;
static int n = 1;
void Fun2 ();
void Fun1 () {
cout << n << Endl;
}
int main () {
Fun1 ();
Fun2 ();
return 1;
}

View plain Copy to clipboard print?
File2.cpp
#include <iostream>
using namespace Std;
extern int n;
void Fun2 () {
cout << n << Endl;
}
Compile two files separately, then connect, there is an error, said n can not find, which means that n only in the File1.cpp effective file2.cpp. Now change the extern int n in file2 to int n = 2, recompile the Run and output: 1 2, which means that file1 and file2 respectively use the n defined in their own file, which is visibility control.
2. Static local Variables
A local variable is defined in the body of the function, and the variable is stored in the stack, and the function returns after the stack is restored. But static local variables are the same as static global variables, and are stored in the global data area. It is also initialized to 0 without being explicitly initialized, and the function returns valid after the function is returned, and the data is still the last result, which has the same effect as the global variable, but the global variable is not just the function itself, Other code can also see that it's easy to break the contents of a variable, so static local variables are useful when you need to save a function's running state.
For example:
View Plaincopy to Clipboardprint?
File3.cpp
#include <iostream>
using namespace Std;
void Fun () {
static int n = 1;
cout << n << Endl;
n++;
}
int main () {
Fun ();
Fun ();
Fun ();
return 1;
}
Compiled, the result will output 1 2 3, indicating that the value of every call to N of the function is saved.
3. Static function
By adding static to the function definition, the function is defined as static, and the visibility of the static function is the same as the static global variable, valid only in the current file and cannot be seen by other files. In addition to these features, static functions are no different from other functions, and this shows the usefulness of the static keyword in controlling visibility.
View plain Copy to clipboard print?
File4.cpp
#include <iostream>
using namespace Std;
static void Fun () {
cout << "Fun" << Endl;
}
View plain Copy to clipboard print?
File5.cpp
void Fun ();
int main () {
Fun ();
}
Compile the two files separately, connect to a program will be an error: Can not find the fun () function, the file4 in the fun function definition of the static remove the OK.
Second, in the application of the class
1, static member variables in the class
When you add static to a class's member variable declaration, the variable becomes a static member variable for the class, for example:
View plain Copy to clipboard print?
File6.cpp
#include <iostream>
using namespace Std;
Class A {
int size;
Public
static int n;
};
int a::n = 1;
int main () {
A A, B;
a::n++;
cout << "a::n =" << a::n << Endl;
cout << "A.N =" << A.N <<endl;
a.n++;
cout << "B.N =" << b.n << Endl;
cout << "sizeof (a) =" << sizeof (a) << Endl;
cout << "sizeof (a) =" << sizeof (a) << Endl;
return 1;
}
The compile operation produces the following output:
A::n = 2
A.N = 2
B.N = 3
sizeof (A) = 4
sizeof (a) = 4
You can see that the static member variables of a class belong to the class itself, not to an object, that all objects see the same n values, and then look at the dimensions of Class A and object A, and only the size of int 4, which means that static member variables and objects themselves are not in the same storage area. In fact, the static stored member variable of the class, as well as other static variables, is store in the global data area, this problem I have encountered in the application for a written test, and then pay attention to.
Initialization of static member variables can take the following form:
< type name > < class name >::< static member variable name > = < value >
References to static member variables can be in the following form:
< class name >::< static member variable name > = < value >
< object name >.< static member variable name >
The meaning of static member variables of a class is that some classes may have properties that are common to all objects, and static member variables can be used at this time, not only to save storage space, but also to see all objects when a public property has changed, and no need to notify all objects. The static member variable of the class, like the normal member variable, can be set to access control, for example, if it is set to private, the variable can only be invoked inside the class.
2. Static member function of class
A static member function of a class, like a static member variable, belongs to a class and not to an object. A member function of a generic class has an implied this pointer as a parameter so that the function can access the member variable of the object, but the static member function does not have this parameter, so the static member function cannot access the member variable of the object and can only access other static members. Here is an example of using a static member function:
View plain Copy to clipboard print?
File7.cpp
#include <iostream>
using namespace Std;
Class A {
int n;
static int m;
Public
void Fun1 () {
A generic function can invoke static and non-static members without special restrictions
cout << n + M << Endl;
Fun2 ();
}
static void Fun2 () {
cout << m << Endl;

Error: Static member function cannot invoke Non-static member
cout << n << Endl;
Fun1 ();
}
};
int main () {
A A;
A::fun2 ();
A.fun1 ();
A.fun2 ();
}
You can see that static member functions and static member variables are invoked the same way.
Third, summary
C + + language has a lot of details, skilled in the code to apply these can greatly improve the robustness of our programs and flexibility. Recently in the job, these questions are easy to be used as a test, where the systematic summary.

Class CA
{
Public
CA (void);
virtual void f () {int a = 10;}
Private
int C;

Char ch;
};

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.