Introduction to C++ (namespaces, default parameters, function overloading, references, inline functions)

introduction

C language is a structured and modular language, suitable for handling smaller-scale programs. For complex problems and large-scale programs that require a high degree of abstraction and modeling, C language is not suitable. In order to solve the software crisis, in the 1980s, the computer industry proposed the idea of ​​OOP (object oriented programming: object-oriented), and programming languages ​​supporting object-oriented programming came into being.
In 1982, Dr. Bjarne Stroustrup introduced and expanded the concept of object-oriented on the basis of C language, and invented a new programming language. In order to express the origin relationship between the language and the C language, it is named C++. Therefore: C++ is produced based on the C language. It can not only carry out the procedural programming of the C language, but also carry out object-based programming characterized by abstract data types, and can also carry out object-oriented programming.

In the previous study of C language, I believe that everyone already has a good understanding of programming in C language, so I will not repeat the basic grammar. In this article, some new knowledge will be introduced to let you get started with C++:

C++ input and output

The first thing to understand is the input and output of C++:

cout is a standard output object , used to write data to the standard output stream (screen);
endl is a manipulator , the effect of writing endl is a newline, and the data in the buffer is flushed to the device;
use the output operator< < can print information on standard output:

std::cout << 表达式1 << 表达式2 << sts::endl;

cin is a standard input object , used to read data from the standard input stream (keyboard);
use the input operator >> to read data from a given input stream into a given object:

std::cin >> 变量1 >> 变量2;

When using cin and cout for input and output, the type of input or output can be automatically identified, and the operation of taking the address is not required. Compared with the C language, the format of input and output needs to be written.

When using cin, cout, and endl, header files need to be included <iostream>, and since their implementations are all in C++标准库命名空间std, it is necessary to introduce namespace or domain scope qualifiers when using them.

Namespaces

Next, introduce the knowledge about namespaces:

In C language, it is often encountered that the variables or functions defined by oneself conflict with the functions defined in the library, or the functions defined by oneself in the project conflict with the functions defined by others. People are bored.
The purpose of using namespaces is to localize the names of identifiers to avoid naming conflicts or name pollution

concept

When defining a namespace, use the keyword namespace, followed by the name of the namespace, and then define members (variables or functions, etc.) in the following {}:

namespace qqq
{
    
    
	int rand = 0;
	int max(int a = 0, int b = 0)
	{
    
    
		if (a > b)
		{
    
    
			return a;
		}
		return b;
	}
}

The rand variable and max function defined in the namespace qqq above are both functions implemented in the library. Defining these two characters in the namespace qqq is equivalent to putting the rand and max in the name In the spatial scope, rather than exposed to the global scope, there will be no naming conflicts.

Namespaces can be nested, and multiple namespaces with the same name can be defined (which will be combined into one when compiling).

use

When using member variables or member functions in a namespace, there are three ways:

use-scope-qualifier::use-a-member

Use scope qualifiers:: When using a member, every time you use a member in a namespace, you must explicitly write 命名空间名::成员名:

//使用域作用限定符::使用某个成员
//省略头文件包含与命名空间qqq
int main()
{
    
    
	int a = qqq::rand;
	int b = 10;
	std::cout << qqq::max(a, b);
	return 0;
}

Use using namespace to introduce the entire namespace domain

When the name is used using namespace 命名空间;to introduce the entire namespace domain, it is equivalent to exposing the entire namespace domain to the global domain, and the members in the namespace become global. It can be used directly when using:

//使用using namespace 引入整个命名空间域
//省略头文件包含与命名空间qqq
using namespace qqq;
using namespace std;
int main()
{
    
    
	int a = rand;
	int b = 10;
	cout << max(a, b);
	return 0;
}

Use using to introduce a member

Although the above method is convenient, exposing the members of the namespace globally makes the namespace lose its original meaning. But for some frequently used functions, the explicit description is too cumbersome, so we can use using 命名空间名 :: 成员名;the method to introduce a certain member, which is equivalent to exposing this member globally, and it can be used directly when using this member later, but don’t The members of still need to be explicitly declared:

//使用using引入某个成员
//省略头文件包含与命名空间qqq
using qqq::max;
using std::cout;
int main()
{
    
    
	int a = qqq::rand;
	int b = 10;
	cout << max(a, b);
	return 0;
}

The cin, cout, and endl mentioned above are all implemented in the standard library namespace std. Of course, you can directly expand the standard library when using: , or you can use it every time, but the safest and most convenient way is to using namespace std;introduce std::the commonly used Members: using std::cout; (eg above).
Besides that, all library functions are in std.

default parameters

When it is necessary to initialize an object, it is much more convenient to set a default value with default parameters than #define in C language to define a constant.

concept

The default parameter is to specify a default value for the parameter of the function when declaring or defining the function. When calling the function, if no actual parameter is specified, the default value of the formal parameter is adopted, otherwise the specified actual parameter is used.

#include<iostream>
void add(int a = 1, int b = 2)
{
    
    
	std::cout << a + b << std::endl;

}
int main()
{
    
    
	add();
	add(10);
	return 0;
}

insert image description here

It should be noted that: in order to avoid the difference between the default value of the definition and the declaration, the definition and declaration of the function cannot set the default value at the same time.

Classification

According to whether the parameter list is completely set to the default value, it is divided into full default and semi-default:

All default parameters means that all parameters in the parameter list are set to default values.
When calling a function with all default parameters, if parameters are passed, the actual parameters will be assigned values ​​to the formal parameters in the parameter list from left to right, and assignments cannot be skipped:

#include<iostream>
void Func(int a = 1, int b = 2, int c = 3)
{
    
    
	std::cout << a << " " << b << " " << c << std::endl;
}
int main()
{
    
    
	//Func(10, , 30);错误调用
	Func();//正确调用
	Func(10, 20);
	return 0;
}

insert image description here

A semi-default parameter is one in which the parameter list does not all set default values.
Semi-default parameters can only give default values ​​from right to left; the number of actual parameters when calling cannot be less than the number of parameters without default values, and are assigned to actual parameters in turn from left to right:

#include<iostream>
//void Func(int a = 1, int b, int c = 3){}错误定义
void Func(int a, int b = 2, int c = 3)
{
    
    
	std::cout << a << " " << b << " " << c;
}
int main()
{
    
    
	//Func();错误调用
	Func(10);//正确调用
	return 0;
}

insert image description here

function overloading

When implementing functions, there are often some functions that have similar functions, but the types of parameters are different. If you define several functions with different function names but similar functions, it will be inconvenient to call. There is function overloading:

Function overloading is a special case of functions. C++ allows several functions of the same name with similar functions to be declared in the same scope. The function is similar to the problem of different data types.

Definition and call

When defining function overloading, the same function name, different number of parameters, different parameter types, and different order of parameter types can constitute overloading:

int Func(int a, int b = 20)
{
    
    
	cout << 1 << endl;
	return 1;
}
int Func(double a, int b)//与第一个函数参数类型不同
{
    
    
	cout << 2 << endl;
	return 2;
}
int Func(int a, double b)//与第二个函数参数顺序不同
{
    
    
	cout << 3 << endl;
	return 3;
}
int Func(int a)//与第一个函数参数个数不同
{
    
    
	cout << 4 << endl;
	return 4;
}

It should be noted that when the parameter list is the same, the difference in the return value does not constitute overloading :

//错误代码,会报错:无法重载仅按返回类型重载的函数
int Func(int a, int b = 20)
{
    
    
	cout << 1;
	return 1;
}
void Func(int a, int b)
{
    
    
	cout << 1;
}

insert image description here
When calling an overloaded function, because the function has default parameters, for example, when only one parameter is passed when calling, it is not known whether to call a function with no default value for the first parameter, or an overloaded function with only one formal parameter, or Other functions that can only pass one parameter. So special care needs to be taken to avoid ambiguity:

Func(10);//错误调用。对于传一个整型,第1个函数与第4个函数均可

insert image description here
Under normal circumstances, the corresponding function can be called according to the passed parameter list:

Func(10, 30);
Func(1.1, 5);
Func(5, 1.1);

insert image description here

principle

So why does C++ support function overloading?

As introduced in the advanced part of C language, before the code we write is converted into an executable program, it has to go through the process of precompiling, compiling, assembling, and linking .
When compiling, a symbol table is generated, and the symbol table includes symbol names and addresses. According to the function name modification rules, each different function will have its own unique symbol. When two functions with the same symbol appear, a compilation error (that is, symbol redefinition) will be reported.

Only after the C language compiler modifies, the function whose symbol name is the same as the function name will be redefined; while the symbol name modified by the C++ compiler will contain information about the function name and parameter list . The overloaded function symbol names are different and will not be redefined. Although the function names are the same when calling, they are actually calling different functions.
However, since the return value type is not included in the decoration rules, the function symbol names with the same function name and parameter list but different return values ​​are also the same, so they cannot constitute overloading.

quote

A reference is an alias , because it essentially uses the same space as the variable it refers to, so the value of the variable it refers to can be changed through the reference variable, and no new space is opened up in the syntax.

definition

Add & after the type to define a reference variable:类型& 引用变量名 = 引用实体;

int main()
{
    
    
	int a = 10;
	int& ra = a;
	int& rra = ra;
	cout << a << " " << ra << " " << rra << endl;
	rra = 20;
	cout << a << " " << ra << " " << rra << endl;
	return 0;
}

insert image description here

In the above code, the integer variable a is defined, the reference variable ra is an alias of a, and rra is an alias of ra, that is, rra is also an alias of a. The three names share a space, and when the value of one of the names is changed, the values ​​of the other two will also change.

requires attention

When defining reference variables, you must pay attention to some issues:

  1. A reference must be initialized when it is defined, that is, it must be clear whose reference it is:
int& a;//错误代码,必须初始化引用
  1. An entity can have multiple references, but a reference variable can only refer to one entity:
int a = 10;
int b = 5;
int& ra = a;
int& rra = ra;
//int& ra = b; 错误代码,ra重定义
  1. Permissions can only be panned or zoomed out when citing, not zoomed in:

When we define a reference variable, we can change the value of the entity through this reference. But for an entity variable with a constant attribute, it is obviously very dangerous to give it an alias that can change its content.
Therefore, for variables with constant attributes, only constant references can be initialized (that is, the reference authority cannot be enlarged):

const int a = 10;
//int& ra = a; 错误代码,权限放大
const int& ra = a; //正确代码

Of course, if you define a constant reference for a non-constant, that is, the reduction or translation of permissions, it is possible:

int b = 5;
const int& rb = b;//正确代码,权限缩小
int& rrb = b;//正确代码,权限平移

Not only variables modified by const, but also the return value of passed value and the variable of type conversion have constant properties. Because they will implicitly copy a copy to a temporary variable when converting, and then assign a value to the temporary variable, and this temporary variable has constant attributes.

  1. A reference type must be the same as its entity type:
int c = 2;
//double& rc = c; 错误代码,引用与实体的类型不同

use

Reference as return type parameter

In the past, for some function implementations that required return parameters, we could only use pointers to pass parameters, which was troublesome both in passing parameters and invoking. It is convenient to use references as return parameters, such as this exchange function:

//命名空间展开与头文件包含已省略
void Swap(int& a, int& b)
{
    
    
	int temp = b;
	b = a;
	a = temp;
}
int main()
{
    
    
	int a = 10;
	int b = 20;
	Swap(a, b);
	cout << a << " " << b;
	return 0;
}

insert image description here
There is no need to take the address when passing parameters, and there is no need to dereference when exchanging. It also looks very clear and is more suitable for return parameters.

reference as return value

The previous return value can only be returned by value or by pointer. When returning by value, there is an implicit copy process, which greatly affects the efficiency for large objects; returning by passing a pointer is not convenient to write. Return by reference is efficient and intuitive:

insert image description here
insert image description here
This kind of code seems to have no problem, and it also realizes the function of Add, but there is a big problem. That is, a local variable is returned by reference. This behavior is very dangerous, because the space of the local variable will be returned to the operating system after the life cycle ends, and the returned reference is an alias of indeterminate data (if the environment will clear the data, it will return any value).

Therefore, you need to pay special attention when using reference return. The value returned by reference must not be destroyed when it goes out of scope . You can return static variables, etc.:

int& Add(int a, int b)
{
    
    
	static int c = a + b;
	return c;
}
int main()
{
    
    
	int a = 10;
	int b = 20;
	int c = Add(a, b);
	cout << c;
	return 0;
}

insert image description here

The difference between reference and pointer

  1. Reference conceptually defines an alias of a variable, and a pointer stores a variable address;
  2. The reference must be initialized when it is defined, and the pointer is not required;
  3. After the reference refers to an entity during initialization, it can no longer refer to other entities, and the pointer can point to any entity of the same type at any time;
  4. There are no NULL references, but there are NULL pointers;
  5. The meaning is different in sizeof: the reference result is the size of the reference type, but the pointer is always the number of bytes occupied by the address space (4 bytes under the 32-bit platform);
  6. The self-referential addition means that the referenced entity increases by 1, and the pointer self-increment means that the pointer offsets the size of a type backward;
  7. There are multi-level pointers, but no multi-level references;
  8. There are different ways to access entities, the pointer needs to be explicitly dereferenced, and the reference compiler handles it by itself;
  9. References are relatively safer to use than pointers;

It should be noted that although the reference does not open up a new space in syntax, it is consistent with the pointer in the underlying logic, and it also needs to open up space to store the address.

inline function

In the C language part, for simple and frequently called functions, we can use macro functions to replace macros in the pre-compilation stage, and save the time and space for functions to open up stack frames to improve efficiency. For example, the macro function ADD:

#define ADD(a, b) ((a)+(b))

Since the macro function is a direct replacement instead of passing parameters, there is no problem with the logic of the macro function, and the writing method is obviously a bit cumbersome.

The inline function can solve such problems: the
modified inlinefunction is called an inline function, and the C++ compiler will expand it at the place where the inline function is called during compilation. efficiency:

inline int Add(int a, int b)
{
    
    
	return a + b;
}

have to be aware of is:

  1. Inline is a way of exchanging space for time. If the compiler treats the function as an inline function, it will replace the function call with the function body during the compilation phase. Defect: It may make the target file larger; Advantage: Less call overhead, improve program running efficiency
  2. Inline is just a suggestion for the compiler. Different compilers may have different inline implementation mechanisms. The general suggestion is to use inline decoration for functions that are small in size, non-recursive, and frequently called, otherwise the compiler will ignore the inline feature.
  3. The declaration of inline functions and variables should not be separated (separate files). Since the inline function is a direct replacement without a function address, if it is separated, it cannot be replaced, and it cannot be called according to the function pointer, and an error will be reported;

Summarize

So far, I have introduced some knowledge about the introduction of C++, and
I will continue to update the knowledge of C++ in the future. You are welcome to continue to pay attention.

If this article is helpful to you, I hope it will be connected with one click

The road to C++ has just begun, let's work together!

Guess you like

Origin blog.csdn.net/weixin_73450183/article/details/130460140