C ++ foundation 01

zhaozj2021-02-12  195

Stack

First we have to understand memory allocation. In general, there are three ways to distribute the memory:

1. Assign from static storage area. There is already a hidden when there is program compilation, and there is existence of the entire running period of the program. For example, global variables, static variables.

2. Create on the stack. When performing a function, the storage unit of local variables within the function can be created on the stack, and the memory cells are automatically released at the end of the function. The stack memory allocation operation is within the command set of the processor, the efficiency is high, but the assigned memory capacity is limited.

3. Allocate from the pile, also known as dynamic memory allocation. The program applies for any number of memory with Malloc or New when running, and the programmer will release the memory with free or delete. Dynamic memory survival is determined by us, it is very flexible, but the problem is most.

The above three allocations, we have to pay attention to the problem of memory life:

1. The life phase of the static allocation is the entire software period, that is, from the software running to the software termination exit. This memory will be recycled by the system after the software is terminated.

2. The life of the space allocated in the stack is related to the functions and classes of this variable. If it is a local variable defined in a function, its life is called when the function is called, and if the function runs, then this memory will be reclaimed. If it is a member variable in the class, its life period is the same as the life of class instance.

3. The memory allocated on the heap is starting from calling new or malloc, and the DELETE or FREE is called. If you don't drop DELETE or FREE. Then this space must be recycled by the system after the software is running.

Multithreading

Process and thread

Handle multiple tasks, speed up efficiency

Mutex

Set the signal, turn on the signal, turn on the signal, complete the operation, turn off the signal before operating the shared resource

Use the status of the event object to perform the access to the shared resource.

Set the rejection area, execute asynchronously in the exclusion area, which can only share resource processing between the threads of the same process, although the above three methods can also be used, but the method of using the rejection area makes the synchronization management efficiency;

In one process of Windows, there is one or more threads, and the thread refers to a execution path of the process, which contains a stand-alone stack and CPU register status, each thread sharing all process resources, including open files, signal identity, and Dynamically allocated memory, etc. All threads in a process use the same 32-bit address space, and the execution of these threads is controlled by the system scheduling program, the scheduler determines the thread to perform and perform threads, threads have priority, and the lower priority thread must Wait until the higher priority thread performs the task and execute it. On the multiprocessor's machine, the scheduler can put multiple threads to run on different processors, which can make the task of the processor to balance the system's operating efficiency.

Socket

Socket is the meaning of the socket, which is an interface that communicates with the computer and the computer.

The pseudo code of the client (C) / server (S) is as follows:

Client:

(1) Socket version negotiation (including started socket)

(2) Establish Socket

(3) Connection

(4) Data transmission

(5) Close Socket

Service-Terminal:

(1) Socket version negotiation (including started socket)

(2) Establish Socket

(3) Bind Socket

(4) Listening connection

(5) Accept the customer request, establish a new socket to handle the user request, where the Socket listening to the connection has always existed

(6) Accept the customer to send data

(7) Close (5) Newly built Socket connection

Close the listener Socket connection

Static variable

Static global variables (objects) refer to the basis of global variables, plus Static modifiers, which have two features of file scope and static survival. Specifically, it means that the variables that are invisible in other source files are only available in the source file defined (file scope). It is the difference between the full variables: the full variable can be explained as an external variable (Extern), which means that the file scope is used by other source files, and the static full variable can not be explained as an external, that is, it can only Use by the source file.

Differences between classes and structures

1. Value type and reference type

Structure is a value type: Value type assigns an address on the stack, all of the base types are structural types, such as: INT corresponds to the System.InT32 structure, String corresponds to the system.string structure, and more value types can be created by using the structure

Class is a reference type: reference type assigns an address on the heap

The implementation efficiency of the stack is higher than the implementation efficiency of the stack, but the resource of the stack is limited, and it is not suitable for processing large logic complex objects. Therefore, structural processing as a small object treated by the base type, and the class handles a business logic

Because the structure is the value type, the assignment between the structure can create a new structure, and the class is a reference type, and the assignment between the classes is just a replication reference.

Note:

1. Although the structure is different from the type of class, but their base type is object (Object), all types of base types in C # are Object.

2. Although the initialization of the structure also uses the New operator, the structural object is still allocated on the stack instead of the pile. If you do not use "New", the field will remain unfaised before initializing all fields, and Object is not available

2. Inheritance

Structure: It cannot be inherited from another structure or class, it cannot be inherited itself, although the structure is not clearly declared, but the structure is implicit SeaD.

Category: Fully scalable unless the displayed declaration Seate, you can inherit other classes and interfaces, it can also be inherited

Note: Although the structure cannot be inherited, the structure can inherit the interface, method and class inheritance interface.

For example: structure implementation interface

Interface Iimage

{

Void paint ();

}

Struct Picture: IIMAGE

{

Public void paint ()

{

// Painting Code Goes Here

}

Private Int x, y, z; // Other Struct Members

}

3. Internal structure:

structure:

There is no default constructor, but can add constructor to add

No destructor

No Abstract and SeaD (because you can't inherit)

No protected modifier

Can not initialize new

The initialization instance field in the structure is wrong

class:

Default constructor

Have a patterned function

You can use Abstract and Sealed

Protected modifier

I must use new initialization

three. How to choose a structure or class

After discussing the same and differences between the structure and classes, the following discusses how to choose to use the structure or class:

1. The stack is limited, for a large number of logical objects, the creation class is better than the creation structure.

2. The structure represents a lightweight object such as points, rectangles, and colors, for example, if a array containing 1000 point objects is declared, the additional memory is assigned to each object. In this case, the cost of the structure is low. 3. The class is the best choice when the abstract and multi-level object hierarchy

4. In most cases this type is just some data, the best choice is

The next five examples specify what is hidden

example 1

#include

Using namespace std;

Class Basic {

PUBLIC:

Void fun () {cout << "Base :: fun ()" << end1;} // overload

Void Fun (INT i) {cout << "Base :: Fun (INT I) << endl;} // overload

}

Class Derive: Public Basic {

PUBLIC:

Void fun2 () {cout << "Derive :: fun2 ()" << endl;}

}

int main ()

{

Derive D;

D.Fun (); // is correct, derived class does not declare the function declaration with the base class, all the overload functions in the base class will be used as a candidate function.

D.Fun (1); // is correct, derived class does not declare the function declaration with the base class, all the same name overload functions in the base class will be used as a candidate function.

Return 0;

}

Example 2

#include

Using namespace std;

Class Basic {

PUBLIC:

Void fun () {cout << "Base :: fun ()" << end1;} // overload

Void Fun (INT i) {cout << "Base :: Fun (INT I) << endl;} // overload

}

Class Derive: Public Basic {

PUBLIC:

// New function versions, all overload versions of the base class are blocked, here, we call the function hide hide

// Declaration of the same name function in the class class, the same name function in the base class does not use the candidate function, even if the base class has multiple versions of the tables in different parameter tables. Overload function.

Void Fun (INT I, INT J) {COUT << "Derive :: Fun (INT I, INT J) << Endl;}

Void fun2 () {cout << "Derive :: fun2 ()" << endl;}

}

int main ()

{

Derive D;

D.Fun (1, 2);

/ / The following sentence is wrong, so shields

//d.fun(); error c2660: 'fun': function does not take 0 parameters

Return 0;

}

Example 3

#include

Using namespace std;

Class Basic {

PUBLIC:

Void fun () {cout << "Base :: fun ()" << end1;} // overload

Void Fun (INT i) {cout << "Base :: Fun (INT I) << endl;} // overload

}

Class Derive: Public Basic {

PUBLIC:

// Overwrite one of the function versions of the Override base class, all overload versions of the same base class are hidden hide

// Declaration of the same name function in the class class, the same name function in the base class does not use the candidate function, even if the base class has multiple versions of the tables in different parameter tables. Overload function. Void fun () {cout << "Derive :: fun ()" << endl;}

Void fun2 () {cout << "Derive :: fun2 ()" << endl;}

}

int main ()

{

Derive D;

D.fun ();

/ / The following sentence is wrong, so shields

//d.fun (1 ); error c2660: 'fun': function does not take pick 1 parameters

Return 0;

}

Example 4

#include

Using namespace std;

Class Basic {

PUBLIC:

Void fun () {cout << "Base :: fun ()" << end1;} // overload

Void Fun (INT i) {cout << "Base :: Fun (INT I) << endl;} // overload

}

Class Derive: Public Basic {

PUBLIC:

Using Basic :: fun;

Void fun () {cout << "Derive :: fun ()" << endl;}

Void fun2 () {cout << "Derive :: fun2 ()" << endl;}

}

int main ()

{

Derive D;

D.fun (); // correct

D.Fun (1); / / correct

Return 0;

}

/ * Output result

Derive :: fun ()

Base :: Fun (INT i)

Press any key to continche

* /

Example 5

#include

Using namespace std;

Class Basic {

PUBLIC:

Void fun () {cout << "Base :: fun ()" << end1;} // overload

Void Fun (INT i) {cout << "Base :: Fun (INT I) << endl;} // overload

}

Class Derive: Public Basic {

PUBLIC:

Using Basic :: fun;

Void Fun (INT I, INT J) {COUT << "Derive :: Fun (INT I, INT J) << Endl;}

Void fun2 () {cout << "Derive :: fun2 ()" << endl;}

}

int main ()

{

Derive D;

D.fun (); // correct

D.Fun (1); / / correct

D.Fun (1, 2); // correct

Return 0;

}

/ *

Output result

Base :: fun ()

Base :: Fun (INT i)

Derive :: Fun (Int i, int J)

Press any key to continche

* /

Overloading OverLoad characteristics:

The same range (in the same class);

The function name is different from the same parameters;

Virtual keywords can be available.

Override Override means that the derived class function overwrites the base class function, the override features are:

Different scope (located in derived class and base class);

The function name and parameter are the same;

The base class function must have a Virtual keyword. (If there is no Virtual keyword, it is called hidden hide) If the base class has multiple overloaded version of a function, you rewrite override in the derived class (override) one or more of the base class. The function version, or re-adds a new function version in the derived class (the function name is the same, the parameters are different), then the overloaded version of all base classes is blocked, here we call Hide. So, in general, you want to use a new function version in the derived class to use the base class's function version, you should rewrite all overload versions in the base class in the derived class. If you don't want to rewrite the overloaded function versions of the base class, you should use Example 4 or Example 5, explicitly declare the base class space scope.

Here "hidden" is a function of generating the bobbin. We also make a summary of the base class function that is the same name.

If the derived class function is the same name, the parameter is different. At this time, if the base class does not have a Virtual keyword, the function of the base class will be hidden. (Note Don't confuse with heavy duty, although the function name is the same parameters, it should be overloaded, but it cannot be understood here, because the derived class and base class are not in the same namespace scope. It is understood here to hide)

If the derived class function is the same name, the parameter is different. At this time, if the base class has a Virtual keyword, the function of the base class will be implicit into the VTABLE of the derived class. The function in the derived type VTABLE points to the function address of the base class version. At the same time, this new function version is added to the derived class as the overloaded version of the derived class. However, when the base class pointer implements a polymorphic call function method, this new derived class function version will be hidden.

If the derived class function is the same name of the base class, and the parameters are the same, but the base class function does not have a Virtual keyword. At this time, the function of the base class is hidden. (Note Don't confuse with the coverage, here is understood to hide).

If the derived class function is the same name, and the parameters are the same, the base class function has a Virtual keyword. At this point, the function of the base class will not be "hidden". (Here, you have to understand it is overwriting ^ _ ^).

Episode: When there is no virtual keyword before the base class function, we have to overwrite more smoothly. When there is a Virtual keyword, we call the overwrite more reasonable, quit, I also hope that everyone can better understand C Some subtle things. Tell, we will explain it.

Example 6

#include

Using namespace std;

Class base {

PUBLIC:

Virtual void fun () {cout << "Base :: fun ()" << endl;} // overload

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i)" << endl;} // overload

}

Class Derive: Public base {

PUBLIC:

Void fun () {cout << "Derive :: fun ()" << endl;} // override

Void Fun (INT i) {cout << "Derive :: Fun (INT I) << Endl;} // override

Void Fun (INT I, INT J) {Cout << "Derive :: Fun (INT I, INT J) <

}

int main ()

{

Base * pb = new deerive ();

PB-> Fun ();

PB-> Fun (1);

/ / The following sentence is wrong, so shields // Pb-> Fun (1, 2); the Virtual function cannot perform Overload, Error C2661: 'Fun': no ​​overloaded function takes 2 parameters

Cout << Endl;

Derive * pd = new derive ();

PD-> FUN ();

PD-> Fun (1);

PD-> FUN (1, 2); // overload

Delete PB;

DELETE PD;

Return 0;

}

/ *

Output result

Derive :: fun ()

Derive :: Fun (INT i)

Derive :: fun ()

Derive :: Fun (INT I)

Derive :: Fun (Int i, int J)

Press any key to continche

* /

Example 7-1

#include

Using namespace std;

Class base {

PUBLIC:

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i) << endl;}

}

Class Derive: Public Base {};

int main ()

{

Base * pb = new deerive ();

PB-> Fun (1); // Base :: Fun (INT i)

Delete PB;

Return 0;

}

Example 7-2

#include

Using namespace std;

Class base {

PUBLIC:

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i) << endl;}

}

Class Derive: Public base {

PUBLIC:

Void Fun (double d) {cout << "Derive :: fun (double d) << endl;}

}

int main ()

{

Base * pb = new deerive ();

PB-> Fun (1); // Base :: Fun (INT i)

PB-> Fun ((Double) 0.01); // Base :: Fun (INT i)

Delete PB;

Return 0;

}

Example 8-1

#include

Using namespace std;

Class base {

PUBLIC:

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i) << endl;}

}

Class Derive: Public base {

PUBLIC:

Void Fun (INT i) {cout << "Derive :: Fun (INT I) << Endl;

}

int main ()

{

Base * pb = new deerive ();

PB-> Fun (1); // Derive :: Fun (INT i)

Delete PB;

Return 0;

}

Example 8-2

#include

Using namespace std;

Class base {

PUBLIC:

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i) << endl;}

}

Class Derive: Public base {

PUBLIC:

Void Fun (INT i) {cout << "Derive :: Fun (INT I) << Endl;} Void Fun (Double D) {cout <<" Derive :: fun (double d) << endl;}

}

int main ()

{

Base * pb = new deerive ();

PB-> Fun (1); // Derive :: Fun (INT i)

PB-> Fun ((Double) 0.01); // Derive :: Fun (INT i)

Delete PB;

Return 0;

}

Example 9

#include

Using namespace std;

Class base {

PUBLIC:

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i) << endl;}

}

Class Derive: Public base {

PUBLIC:

Void Fun (INT i) {cout << "Derive :: Fun (INT I) << Endl;

Void fun (char c) {cout << "Derive :: fun (char c)" << endl;}

Void Fun (double d) {cout << "Derive :: fun (double d) << endl;}

}

int main ()

{

Base * pb = new deerive ();

PB-> Fun (1); // Derive :: Fun (INT i)

PB-> Fun ('a'); // Derive :: Fun (INT i)

PB-> Fun ((Double) 0.01); // Derive :: Fun (INT i)

Derive * pd = new derive ();

PD-> Fun (1); // Derive :: Fun (INT i)

// overload

PD-> Fun ('a'); // Derive :: Fun (Char C)

// overload

PD-> Fun (0.01); // Derive :: Fun (Double D)

Delete PB;

DELETE PD;

Return 0;

}

Examples 7-1 and Example 8-1 are very good, I put these two examples here, let everyone make a relatively, and to help everyone better understand:

In N: 7-1, the derived class does not cover the virtual function of the base class. At this time, the address of the function pointer in the VTABLE of the derived class is the virtual function address of the base class.

In N, the derived class covers the virtual function of the base class. At this time, the address of the function pointer in the VTABLE of the derived class points is the virtual function address that derives its own rewriting.

It looks a bit weird in Case 7-2 and 8-2. In fact, you compare it in accordance with the principles above, the answer is clear:

N-Class 7-2, we overload a function version for the derived class: Void Fun (Double D) is actually an observatory. We specifically analyze that there are several functions in the base class, and there are several functions of the derived class:

Types of

Base class

Derived class

VTABLE section

Void Fun (INT i)

Point to the base class version of the virtual function Void Fun (INT i)

Static part

Void Fun (Double D)

Let's analyze the following three codes.

Base * pb = new deerive ();

PB-> Fun (1); // Base :: Fun (INT I) PB-> Fun ((Double) 0.01); // Base :: Fun (INT i)

This first sentence is the key, the base class pointer points to the object of derived class, we know this is a polymorphic call; next sentence, the runtime base class pointer is found to be derived objects according to the type of time object, so first In the VTABLE who derived class, find the virtual function version of the school, and found that the derived class does not overwrite the virtual function of the base class, the derived type of VTable is just a point to point to the base class virtual function address, so it is reasonable to call the base The virtual function of the class version. In the last sentence, the program is still buried to find VTABLE who is derived, and found that there is no virtual function at all, I have to turn back to call my own virtual function.

It is also worth mentioning that if the base class has multiple virtual functions, "call is not clear" when the program is added. Example

#include

Using namespace std;

Class base {

PUBLIC:

Virtual Void Fun (INT I) {cout << "Base :: Fun (INT i) << endl;}

Virtual Void Fun (Char C) {cout << "Base :: fun (char c) << endl;}

}

Class Derive: Public base {

PUBLIC:

Void Fun (double d) {cout << "Derive :: fun (double d) << endl;}

}

int main ()

{

Base * pb = new deerive ();

PB-> Fun (0.01); // Error C2668: 'Fun': Ambiguous Call To overloaded Function

Delete PB;

Return 0;

}

Ok, let's analyze the exam 8-2.

N-8-2, we also overload a function version for derived classes: Void Fun (Double D), and override the virtual function of the base class, let's take a specific analysis, the base class has several functions, derived A total of several functions:

Types of

Base class

Derived class

VTABLE section

Void Fun (INT i)

Void Fun (INT i)

Static part

Void Fun (Double D)

From the table we can see that the function pointer in the derived type of VTABLE points to your own overwritten virtual function address.

Let's analyze the following three codes.

Base * pb = new deerive ();

PB-> Fun (1); // Derive :: Fun (INT i)

PB-> Fun ((Double) 0.01); // Derive :: Fun (INT i)

The first sentence does not have to say more, the second sentence, I have a derived virtual function version, the third sentence, hey, I feel stupid, in fact, the C program is very stupid, when running, burying into the head In the VTABLE table of the derived class, only the eyes, relying on the version, "I really can't do it, why don't I find it around? Oh, it is limited to the eye, the base class is old Old, I will definitely be old flower, it's just that it is only my own non-VTABLE section (ie, static part) and the VTABLE section you want to manage, the Void Fun (Double D) of the derived class is so far, see Not arrived! Rapid, derived, do you have a little power? Hey, no noisy, you can do your own ^ _ ^ ^! You want to sigh, base class pointer Can make polymorphic calls, but never perform derived overload calls (Reference Example 6) ~~~

summary:

The overload OverLoad is the function version to be called based on the parameter list of functions, and the polymorphism is based on the actual type of runtime object, and the virtual Virtual function version to be called, the polymorphic implementation is based on the classification class If the virtual Virtual function is overridden override, if the class is not overwriting Override if there is no virtual virtual function for the base class, the derived class will automatically inherit the virtual Virtual function version of the base class. At this time, regardless of the object that the base class pointer points to the object. The base type or derived type, will call the base class version of the virtual Virtual function; if the derived class overrides the virtual Virtual function of the base class, the virtual Virtual function version to be called according to the actual type of object is running at runtime. For example, the object type of the base class pointer is a derived type, and the derived virtual Virtual function version is called to achieve polymorphism.

The purpose of using polymorphism is to declare the function to Virtual in the base class, and it is to override the virtual Virtual function version of the Override base class in the derived class. Note that the function prototype is consistent with the base class at this time, the same name Parameter type; if you add a function version in the derived class, you cannot dynamically call the new function version of the derived class through the base class pointer, this new function version only uses an overload version of the derived class. Or the same sentence, the overload is only valid in the current class, whether you are overloaded in the base class, or in the derived class, both are not implicated. If you understand this, in Example 6, Example 9, we will also understand its output results.

The overload is static, and the polygon is dynamically coupled. Further explanation, the overload is independent of the type of object that the pointer is actually pointed, and the polymorphism is related to the object type that the pointer is actually pointed. If the base class pointer is called the overload version of the derived class, C is determined that the C sector only believes that the base class pointer can only call the base class's overload version, and overload only the namespace only in the current class. The domain is effective, inheritance will lose heavy-duty characteristics, of course, if the base class pointer is called a virtual Virtual function, then it will also perform the virtual Virtual function version of the base class or the virtual virtual function version of the derived class. To make specific operations, this is determined by the object type actually pointed to by the base class pointer, so that the overload is independent of the object type that the pointer actually points, the polymorphism is related to the object type that is actually pointed to by the pointer.

Finally, the virtual Virtual function can also be overloaded, but the overload can only be valid in the current namespace scope (please refer to Example 6 again).

转载请注明原文地址:https://www.9cbs.com/read-6757.html

New Post(0)