C++: Classes and Objects (Part 1) --- Preliminary understanding of classes and this pointer

procedural and object oriented

C language is a process-oriented language that focuses on the process, confirms the steps to solve a problem, and then solves it step by step

C++ is an object-oriented language. It pays more attention to objects, divides a thing into different objects, and then uses objects to solve problems.

class introduction

There are structures in the C language, but only variables can be defined in the structure, and functions can also be defined in C++. For example, functions such as linked lists, stacks, and queues in the data structure need to define members, define functions externally, and change them through functions The content of the specific data structure, and in C++, functions can also be defined in the structure, which is an improvement of C++ to C

class definition

class className
{
// 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号
  1. class is the keyword to define the class, ClassName is the name of the class, and {} is the body of the class. Note that the semicolon after the end of the class definition cannot be omitted.

  2. The contents of the class body are called members of the class: variables in the class are called attributes or member variables of the class; functions in the class are called methods or member functions of the class.

The way the class is defined

  1. Both the declaration and the definition are placed in the class body. It should be noted that if the member function is defined in the class, the compiler may treat the member function as an inline function.

The specific definition form is as follows:

#include <iostream>
using namespace std;

class Time
{
    
    
public:

	void settime()
	{
    
    
		cin >> hour >> minute >> second;
	}

	void show()
	{
    
    
		cout << hour << endl;
		cout << minute << endl;
		cout << second << endl;
	}

private:
	int hour;
	int minute;
	int second;
};

int main()
{
    
    
	Time t1;
	t1.settime();
	t1.show();
	return 0;
}
  1. The class declaration is placed in the .h file, and the definition is placed in the .cpp file. Generally speaking, it is more desirable to use this way of writing

insert image description here

class access qualifier

Regarding access qualifiers:

  1. Publicly modified members can be directly accessed outside the class
  2. Protected and private modified members cannot be directly accessed outside the class (here protected and private are similar)
  3. Access scopes start at the occurrence of this access qualifier until the next occurrence of the access qualifier
  4. If there is no access qualifier behind, the scope will go to }, which is the end of the class.
  5. The default access permission of class is private, and struct is public (because struct is compatible with C)

class instantiation

Generally speaking, the process of creating an object with the type of the class is the instantiation of the class

We can understand this way that a class is a design drawing, and only by realizing the design drawing can there be actual space and occupy memory space. Therefore, the class itself has no space, and only by instantiating the class into an object can there be actual space

class object model

class object size

Now that a class is created, what is contained in the object of this class, and how to calculate the size of a class

Suppose we have the following code

#include <iostream>
using namespace std;

class date
{
    
    
public:
	void print()
	{
    
    
		cout << "void print()" << a << endl;
	}
private:
	int a;
};

int main()
{
    
    
	date d1;
	cout << sizeof(date) << endl;
	cout << sizeof(d1) << endl;
	cout << &d1 << endl;
}

insert image description here
So how exactly is the class size calculated? The following is an introduction to the storage method of the class

In C++, objects are stored like this:

insert image description here

Therefore, the members of the class exist independently, and the member functions of the class are placed in the common code area

The members of a class can be added independently. Its rules are actually the same as the calculation of the structure, and they are added according to the memory alignment rules.

The proof of the public code area can also be viewed through assembly

insert image description here
It can be seen from this that the member functions of the class are indeed called in a fixed public code area when they are called, so we understand how the class is stored inside the computer

But there are still two exceptions:

// 类中仅有成员函数
class A 
{
    
    
public:
	void f2() {
    
    }
};

// 类中什么都没有---空类
class B
{
    
    };

int main()
{
    
    
	cout << sizeof(A) << endl;
	cout << sizeof(B) << endl;
}

When there are no members in the class or it is directly an empty class, their size is 1. This 1 has no practical meaning, but is used to occupy a place, proving that A and B once existed here

this pointer

The concept of this pointer is also introduced in C++, which is a more secretive content

The reason for the introduction of this pointer

When we create a class and use the class to define variables, and then use the variables to call member functions in the public code area, do you have such a problem: the function body does not write the distinction between different objects, so different variables call the function , how does the function determine which variable to act on?
This is the credit of this pointer

The this pointer is introduced in C++, and this this pointer is the pointer parameter of each non-static member function, that is to say, the actual parameter of each member function has one more pointer parameter than its surface parameter, and the meaning of the existence of this pointer It is to point to the current object when calling, this operation is automatically completed by the compiler, the whole process is transparent, and the user does not need to complete these operations

The following code and diagram to explain:
Now there is such a code:

#include <iostream>
using namespace std;
class date
{
    
    
public:
	void print(int year)
	{
    
    
		a = year;
	}
private:
	int a;
};

int main()
{
    
    
	date d1;
	date d2;
	d1.print(2004);
	d2.print(2003);
}

On the surface, the parameter of the print function is only one year, and when d1 and d2 call the print function, there is only one parameter passed, but in fact, it is like this inside the compiler

insert image description here

Characteristics of this pointer

  1. The type of this pointer: class type * const, that is, in member functions, the this pointer cannot be assigned a value.
  2. Can only be used inside a "member function"
  3. The this pointer is essentially a formal parameter of a "member function". When an object calls a member function, the object address is passed as an actual parameter to this formal parameter. So the this pointer is not stored in the object.
  4. The this pointer is the first implicit pointer parameter of the "member function". Generally, it is automatically passed by the compiler through the ecx register and does not need to be passed by the user.

About understanding the this pointer

// 下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
    
    
public:
	void Print()
	{
    
    
		cout << "Print()" << endl;
	}
private:
	int _a;
};
int main()
{
    
    
	A* p = nullptr;
	p->Print();
	return 0;
}

Compile and run can run normally, the reason is the problem of the storage location of the member function mentioned above

The problem with this question is that here p is a null pointer. Isn't it wrong for me to directly dereference the null pointer?
In fact, there is no dereferencing at all here. First of all, it must be clear that dereferencing means that I want to use a pointer to access a certain content in this space area. This process is dereferencing, and does the Print function exist in the object? ? Obviously not, the member function is stored in the public code area, here it seems that the dereferencing is actually just an ordinary function call, and this phenomenon can be well explained by assembly

Here we comment out the private so that the pointer can access the member _a inside the object

insert image description here
The assembly at the bottom is dereferencing. We want to access the data _a inside the object. Of course, the null pointer cannot be dereferenced...
But the key point is better explained. The above statement just simply calls the Print function. The first The sentence is to pass the this pointer to the function, which is the so-called parameter passing. The second sentence call is the so-called call. The essence of executing the function is to pass parameters and call. This problem can be better understood from the assembly

If you still have doubts about this, take a look at the following example comparison

class Date
{
    
    
public:
	void Print()
	{
    
    
		cout << this << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
    
    
	Date d1;
	d1.Print();

	Date* p2 = nullptr;
	p2->Print();

	return 0;
}

insert image description here

The above code means to call the Print function to print the value of the this pointer. The this pointer is actually the address of the object. This code can better explain what we explained earlier. The member function is called after passing the this pointer parameter. function call

If you understand the above question, there is a similar question below:

class A
{
    
    
public:
	void PrintA()
	{
    
    
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
    
    
	A* p = nullptr;
	p->PrintA();
	return 0;
}

If you understand the above question, the following question is very simple. The only difference here is that the value of the member is to be printed in the Print function, but this->_a is actually printed. Therefore, the this passed as the parameter is nullptr , so the program crashes with

Guess you like

Origin blog.csdn.net/qq_73899585/article/details/131827237