C++ basic grammar (namespace, default, overload)

Foreword: The knowledge of C++ grammar is complicated, and there are many details to consider. It is not a good way to learn C++ well from the beginning. The content of books is generally more rigorous, but for beginners, many concepts cannot be understood , You may be hit in the head when you come up. Therefore, it is recommended to learn C language well before learning C++, and then listen to the introductory courses. C++ has many grammatical concepts that are a supplement to C language. After learning C language, you can better understand why it is designed in this way. I am also a beginner. This kind of article written is only for summary of notes and analysis and discussion of some concepts, which is convenient for future recall. Due to limited knowledge, mistakes are inevitable. Welcome to read and advise

Table of contents

Namespaces

Namespace definition

namespace extension

default function

Definition of default functions

Attention should be paid to the default parameters 

function overloading

Definition of function overloading

List of situations that can constitute function overloading

Application and underlying implementation of function overloading


Namespaces

Namespace definition

Read the following two pieces of code and print "hello C++" in C++ and C respectively to see the difference

#include <iostream>

using namespace std;

int main()
{
	cout << "hello C++" << endl;
	return 0;
}



#include <stdio.h>

int main()
{
	printf("hello C++");
	return 0;
}

When we look at the C++ code written by others, we seem to always see the statement using namespace std. The printout function of C++ is cout. This is understandable and there is no problem. Then why add using namespace std, which is related to the namespace Well, this problem, we will solve it later, look at the following piece of code

#include <stdio.h>

int num = 20;

int main()
{
	int num = 10;
	printf(" %d ", num);
	printf(" %d ", num);
	return 0;
}

The global variable num and the local variable num have the same name. According to the regulations of the C/C++ compiler, check from the local first. If there is a definition of the variable locally, then use the local variable. If the definition of the variable cannot be found locally , then go to the global search, so the result of the two prints is 10, but I want to print both the global num and the local num? C language does not support this form. To print out both the global num and the local num, C language must have a variable that needs to be renamed, but C++ can do it. How can C++ do it? Look at the following piece of code

#include<iostream>

using namespace  std;

namespace  test
{
	int num = 20;
}

int main()
{
	int num = 10;
	cout << num << endl;
	cout << test::num << endl;
	return 0;
}

First ignore the line of code using namespace std, look at namespace test, namespace is the keyword of the namespace, namespace test is to define a space domain named test, the space domain is equivalent to a wall, enclosing int num = 20 After being surrounded, the compiler will not check in the domain space, so that it will not cause naming conflicts with the num in the local

So what should I do if I want to use int num = 20 in the namespace? At this time, you need to use the domain qualifier " :: ", that is, test :: num, to tell the compiler to find num in the space domain of test. At this time, the num in test is printed. It should be noted that int num = 20 Although it is in the test space domain, num is still stored in the global static area. The test is only equivalent to a wall, which will not affect its internal definition and declaration. It can be seen that the namespace can play a protective role and solve the problem. conflicts between variables with the same name

In order to prevent our personal variable or function naming from conflicting with the naming in the official library, C++ officially puts the standard library functions in the std space domain, that is to say, our commonly used output functions cout and newline endl are all defined in std In the space domain, if you want to use cout, endl needs to be specified with a domain operator, such as std::cout, std::endl

Without std::, the compiler doesn't know cout and endl at all 

After adding std::, it can be compiled normally, and the problem comes again. Every time you use cout and endl, you must use the domain qualifier:: to specify, which is too troublesome. The C++ official allows using namespace std; this What do you mean by this way of writing?

Isn't cout surrounded by the wall of std? Using namespace std is equivalent to digging a big hole in the wall of std, and the definitions inside are exposed to the global domain. At this time, when the compiler compiles again, it can If we find cout in the global area, we don't need to use std:: to specify it. Of course, although there is a hole, it is still inside, so we can still find cout with std::

Although using namespace std can help us to be lazy, it will cause a serious problem. Your cout is exposed to the global domain. If I define my own cout function in the global domain, won’t this cause a naming conflict? , so we can be lazy to use it when we practice, and use it with caution in an unclear environment

You may say that I just use cout frequently, and I don’t want to expose the contents of the entire std domain. The intimate C++ also provides using std :: cout; This means that only the content of cout is exposed to the global domain, other content within std is still under the domain protection of std

namespace extension

You may be wondering about the above code, int num = 20; is not protected by the domain, why not just print the num in the part? On the contrary, both of them can be printed out. There are more :: in the second printing function. If the left side of :: is empty, it will default to the global domain. We mentioned the C/C++ compiler regulations before, and look for variables The rule is to search from the local first. If there is a definition of the variable locally, then use the local. If the definition of the variable cannot be found locally, then go to the global to find it.

And here, there is obviously a definition of num in the local area, but when printing the second num, :: is added, which tells the compiler that you go to the global domain to find num, if you do not add the domain qualifier:: , then the compiler will not look for it in the global domain, and the result of the two prints is 10

Looking at the above code, I defined the namespace test in the two files "C++test.h" and "C++test.cpp" at the same time, and found that it can run in the test file and get the correct Result 3, this is another rule of the namespace,

Under the same project, the same domain names in different files will be merged into one space domain , that is, the same name space domain test in the two files "C++test.h" and "C++test.cpp" will be merge into one spatial domain

default function

Definition of default functions

The default function is to assign a predetermined value to a parameter when defining a function. If this parameter is not passed a value when calling this function, then the default parameter will use this predetermined value. What does it mean? ?

In the program in the above figure, I want to add the values ​​of x and y together, and then multiply it by Z to return, but I did not pass parameters to Z, and finally got the result 30

The detail is that when I define Z, I assign a value of 10 to Z, which means that when calling this function, you don’t need to pass parameters to Z. If you pass parameters to Z, then the value of Z is the value you passed in the past. If If you don’t pass parameters to Z, then Z will use the predetermined value you gave when you defined it. At this time, Z is the default parameter, and the function Add is the default function

When defining a function, you can set all its parameters as default parameters. The above program is changed in the figure below, and the three parameters are all set to default values. When calling, I do not assign values ​​and get the result 3

Attention should be paid to the default parameters 

When defining a default function, it should be noted that the default parameters must be defined from right to left

int Add(int x = 1, int y , int Z = 1) //No, not from right to left

int Add(int x , int y  = 1 , int Z = 1) //可以

int Add(int x = 1, int y = 1, int Z) //No, not from right to left

int Add(int x = 1, int y  = 1, int Z = 1) //可以

When passing parameters to the default function , the parameters must be passed from left to right, and cannot be skipped

Default function: int Add(int x = 1, int y = 1, int Z = 1)

Call case 1: Add(1, 2, 3) //Yes

Calling case 2: Add(1, 2) //Yes

Calling case 3: Add(1) //Yes

Calling situation 4: Add(1, , 3) ​​//No, no parameters are passed sequentially, and one is skipped in the middle

Calling situation 5: Add( , , 3) ​​//No, there is no sequential parameter passing

When defining a default function, the default parameter cannot appear in both the declaration and definition of the function

What does that mean? look at the picture below

There is no specific regulation whether it appears in the definition or in the declaration, and generally appears in the declaration of the function 

function overloading

Definition of function overloading

What is function overloading? When we write a project program, if we refer to functions in other files, the name of the function we defined may be the same as the name of the function in other files. If your function is called a lot, it is very easy to change the function name. Trouble, and tampering with function names in other files may cause inexplicable problems. This situation is very troublesome, and C++ provides us with function overloading to solve this problem

C++ allows two or more functions to have the same name. The same name is fine, but the parameters of the functions must be different. Different parameters refer to the number of parameters, the types of parameters, and the order of parameters (the order refers to the order of types) . Two or more functions with the same name and different parameters constitute function overloading.

The three test functions in the figure above constitute function overloading. The three test functions have the same function name, but their parameters are int char double and different parameter types, which can constitute function overloading.

List of situations that can constitute function overloading

Due to space reasons, the definition of the function will not be written here, only the declaration will be shown

int test(int x, int y)           int test(int x,  int y,  int z)

The above two functions can constitute function overloading because the number of parameters is different

int test(int x, int y)           char test(char x,  char y)

The above two functions can also constitute function overloading, because the types of parameters are different

int test(int x, char y)           int test(char x,  int y)

The above two functions can also constitute function overloading, because the type order of the parameters is different

int test(int x, int y)        int test(int y, int x)

The above two functions cannot constitute function overloading, because this is not the order of the types, but the order of the variable names is different

Application and underlying implementation of function overloading

After understanding function overloading, everyone can understand how the cout function realizes automatic identification of variable types

cout is essentially composed of many overloaded cout functions with the same name. The input parameter value will be passed to the cout function corresponding to its type when printing, so as to print out the corresponding type of result

The underlying implementation of function overloading

How is function overloading achieved? Why can you find the corresponding function when you input different types of values? How to distinguish overloaded functions with the same function name at the bottom? Let's discuss one by one, here is just a simple discussion, because the process is very complicated, it will be very troublesome to expand

The compiler will analyze and summarize various symbols that appear during the compilation stage, including variable names, function names, etc., to form a symbol table, which is convenient for subsequent programs to call functions. If you want to see how the underlying layer distinguishes overloaded functions, you need to see how the overloaded functions are recorded on this symbol table, because different compilations have different symbol naming rules in the symbol table, we Take g++ in linux as a reference

Suppose the following two functions are called in our program

int test(int x, int y)         double test(double x, doubley) 

Then after compilation, in the symbol table, the symbolic names of the two functions are

<_Z4testii>     <_Z4testdd>

It can be seen that the symbol names of the two overloaded functions are the combination of the function name and the parameter type abbreviation, which corresponds to the previous rules of function overloading

Some students may have such a question: If the function names of two functions are the same, and the parameters are all the same, but the types of return values ​​are different, can this constitute function overloading? The answer is no, you may say that if you add the type of the return value to the symbol table, you can recognize that these are two different functions.

Indeed, the compiler can recognize that these are two functions. The crux of the problem is that the compiler doesn’t know which function to return. When you call the function, you only pass parameters, and you don’t say which type to return. Causes ambiguity, so overloaded functions cannot be designed with the type of return value

`

Guess you like

Origin blog.csdn.net/m0_61350245/article/details/126941845