C++ Basic Grammar (under Objects)

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 type 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 and vision, mistakes are inevitable. Welcome to read and advise

When I wrote this article on classes and objects, I knew that in order to understand classes and objects, I had to go through a lot of practice. Based on my beginner’s few words, I must be full of mistakes. After thinking about it, I might as well write about beginners. For the understanding of classes and objects, describe the classes and objects in your own eyes, and share your own views, which may provide you with a different perspective. Welcome to advise

The previous article mentioned several special member functions in the class. These member functions must be mastered throughout the study of the entire C++ class. This article then explores the characteristics of the C++ class, including delving into the constructor, friend , static members, etc.

Table of contents

initialization list

What is an initializer list

 Use of initialization lists

implicit type conversion

What is implicit type conversion

explicit

static member

static members in the class

Tomomoto

friend function

friend class

inner class

anonymous object


 

initialization list

What is an initializer list

When it comes to initialization lists, we need to mention constructors, because initialization lists and constructors are closely related

We have learned before that the initialization of class instantiation is done by the constructor, and the compiler will automatically call the constructor, but in fact the initialization is not done by the constructor

At this point, everyone should understand the concept of initialization. Initialization can only be performed once, which is the value assigned when the variable is defined. Subsequent value change operations are called assignments. The actual variable is not defined in the constructor . So the constructor only assigns values ​​to variables, not initializes them.

Where is the initialization work done? According to the above, if you want to know who is responsible for the initialization, you need to know where the variable is defined, because the value assigned when the variable is defined is called initialization.

 Use of initialization lists

Presumably everyone has already guessed the answer. Variables are defined in the initialization list. Every variable is defined in the initialization list. Whether it is a built-in type or a custom type, we can write it manually. Generate it yourself. If you want to write it manually, where is the initialization list?

The initialization list is between the definition line of the constructor and the function block. Let's take the stack class as an example

The above figure just shows where the initialization list is defined, now look at the rules for initializing variables in the initialization list

Initialization list: starts with a colon, followed by a comma-separated list of data members, each "member variable" is followed by an initial value or expression in parentheses This also explains why the compiler itself
generates The default constructor does not deal with built-in types, because the default constructor generated by the compiler only goes through the initialization list, that is to say, only the declared variable is created, and the value in the variable is not indicated in the initialization list. , so it is a random value

The constructor we wrote ourselves will also create the declared variable type in the initialization list first. If we give the initialization value of a variable in the initialization list, the specified value will be used

Variables that are not specified are random values ​​after they are defined in the initialization list, and then the program fetches the contents of the function block that executes the constructor, so the completion of the initialization list does not mean that the constructor is over, but that the The types declared in are all created, the initialization is over, and then the content in the function block of the constructor is executed, but the assignment operation in the function block is no longer an initialization, but an assignment operation

It seems that the initialization list is useless. We usually assign values ​​​​in the function block of the constructor. As for whether it is initialized or not, what does it matter? This is because we forgot that not all variables can be written in the constructor block

For example, variables modified by const, references, and built-in types without default construction

These three have a common feature, that is, they must be initialized when they are created (or defined). These three types cannot be assigned in the function block of the constructor, but must be written to the initialization list. , it is recommended that you use initialization lists as much as possible

Another point to mention is that when the initialization list is initialized, it is initialized in the order in which the variables are declared in the class, not in the order in which they are initialized in the initialization list. For example

implicit type conversion

What is implicit type conversion

Constructors support implicit type conversion by default, and we can understand implicit type conversion well through a few examples

//接下来我们用这些代码来解释隐式类型转换


class test
{
public:

	test(int tmp)
	{
		_a = tmp;
	}

private:
	int _a;
};

int main()
{
	test p1(10);
	test p2 = 10;

	return 0;
}

Both p1 and p2 are initialized to 10, but the process they go through is different. p1 is initialized by calling the constructor directly, while p2 is initialized through implicit type conversion. This process includes creating a temporary The object temp of the test class (this name is created by myself, which is easy for everyone to understand), one construction, one copy construction

The current compiler is smarter, and may directly optimize the process of p2 implicit type conversion, and complete the initialization with one construction like p1, which depends on the compiler

The original C++98 standard supports implicit type conversion for a single parameter or a constructor with a default value except for the first parameter without a default value.

//单参构造,支持隐式类型转换
class test
{
public:

	test(int tmp)
	{
		_a = tmp;
	}

private:
	int _a;
};

int main()
{
	test p1(10);
	test p2 = 10;

	return 0;
}



//虽是多参数构造,但只有第一个参数无默认值,所以支持隐式类型转化
class test
{
public:

	test(int a, int b = 10, int c = 20)
	{
		_a = a;
		_b = b;
		_c = c;
	}

private:
	int _a;
	int _b;
	int _c;
};

int main()
{
	test p1(10);
	test p2 = 10;

	return 0;
}

After the C++11 standard, implicit type conversion of multiple parameters is supported, and curly braces are used for implicit type conversion of multiple parameters

//C++11之后支持多参数隐式转换

class test
{
public:

	test(int a, int b, int c)
	{
		_a = a;
		_b = b;
		_c = c;
	}

private:
	int _a;
	int _b;
	int _c;
};

int main()
{
	test p1(10, 20, 30);
	test p2 = {10, 20, 30};

	return 0;
}

explicit

What is explicit? The implicit type conversion we mentioned above, the constructor allows this operation by default, but if you don't want to perform implicit type conversion, then you can add the keyword explicit in front of the constructor such that the constructor Implicit type conversion is not supported, and the writing method of p2 in the above code is not allowed

static member

static members in the class

Compared with ordinary variables, static static variables differ in their life cycle. Static member variables are stored in the static area. When the program terminates, their life cycle will end. The life cycle of static variables is the same, but they are defined when they are not used. The scope of the static variable of the location is different. The static variable defined in the global domain is also a global variable. The scope is global and can be shared by the entire program, while the static variable defined in a certain function or in a certain class Static variables, whose scope is only within the function or class, only the function or class can use

And the next thing we understand is the static members in the class

class test
{
public:

	test(int b = 10, int c = 20)
	{
		_b = b;
		_c = c;
	}

private:
	static int _a;  //仅是声明
	int _b;
	int _c;
};


//类中的静态成员不是在类中进行初始化的,而是在类外进行初始化
int test::_a = 30; 

It is not difficult to understand that the static variable defined in the class is shared by all objects of the class. If it is initialized in the class, it is not possible to initialize the static variable every time an object is defined.

In addition to defining static variables in a class, you can also define static functions. What is the difference between a static function and a member function in a class? The biggest difference is that static functions do not have this pointer, that is to say, static functions cannot access member variables in the class, but static functions can access static variables in the class, which is used in conjunction with static variables in the class

We collectively refer to the static variables and static functions in the class as static members, and get the following characteristics

1. Static members are shared by all class objects, do not belong to a specific object, and are stored in the static area 2.
Static member variables must be defined outside the class, and the static keyword is not added when defining, just declared in the class
3. Class static Members can be accessed by class name:: static members or object. static members
4. Static member functions have no hidden this pointer and cannot access any non-static members
5. Static members are also members of classes, subject to public, protected, and private access restrictions character limit

Tomomoto

friend function

In some specific cases, a function defined outside the class needs to access the member variables in the class. If it is too troublesome to access the member variables in the class through other means, C++ allows functions modified by friends to directly access the class. In simple terms, the member variable in is to open a small door. Some undocumented personnel can enter through the small door. The function modified by the friend destroys the encapsulation of the class, so we need to be careful

To get a friend of a certain class, it needs to be declared by the keyword friend in the class, for example

We define a void Check_val_of_test() function outside the class to access the members of the class

Some notes about friend functions:

Friend functions can access private and protected members of the class, but not member functions of the class.
Friend functions cannot be modified with const.
Friend functions can be declared anywhere in the class definition, and are not limited by class access qualifiers.
A function can be multiple class friend function

friend class

If class A is set as a friend class of class B, then all member functions in A are friend functions of class B, that is to say, all member functions in A can access private member variables in B

Friend classes are one-way. The member functions in A above can access the private variables in B, but not the other way around.

The friendship relationship cannot be passed. Suppose class A is a friend of class B, and class B is a friend of class C. It cannot be said that class A is a friend of class C. Class A cannot directly access the private member variables of class C.

inner class

Suppose there are two classes, class A and class B, if class B is defined inside class A, then class B is said to be the inner class of class A, and class A is the outer class of class B

The inner class does not belong to the outer class, it is not stored in the outer class, but it can access
all members of the outer class through the object parameters of the outer class, that is to say, the inner class is a metaclass of the outer class

But you can't access any member of the inner class through the object parameters of the outer class . This rule is so strange, but since it is a rule, it has its own reasons, so I won't guess here

Some Characteristics of Inner Classes

The inner class can be defined in the public, protected, and private of the outer class. The
inner class can directly access the static members in the outer class, and the object/class name of the outer class is not required.
sizeof (outer class) = outer class, and inner class not related

anonymous object

Anonymous objects do not need to give the object a name, but the life cycle of an anonymous object is only one line, for example

class test
{
public:
	
	test(int b = 10, int c = 20)
	{
		_b = b;
		_c = c;
	}

private:
	int _b;
	int _c;
};


int main()
{
   test();   //这样就定义了一个匿名类,但是其生命周期只有这一行
             //从这行开始,上面定义的匿名类就销毁了
   return 0;
}

You may think that anonymous classes are useless. Think about a scenario where I want to call a function in a class, but I don't want to define an object of that class. I just want to call a function. Do this It is a waste of space. At this time, we can use anonymous objects to solve this problem very well. Anonymous objects can call member functions of this class. After the function call is completed, the class will be destroyed. It can be seen that it is still very useful.

Guess you like

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