Explain C++ classes & objects in detail (Part 1), take you into C++

Table of contents

1. Object-oriented & process-oriented understanding (simple understanding is enough, gradually understanding)

Two, class

2.1 Introduction of class 

2.2 Class Definition

1. struct 

2. class 

There are two ways to define a class:

2.3 Encapsulation & Class Access Qualifiers 

1. Packaging concept

2. Class access qualifiers 

2.4 Scope of classes

2. 5 class object model

1. Calculate the class size

2. The storage method of class objects

2.6 Structure memory alignment rules

2. 7 this pointer

1. This pointer characteristics

2. This pointer interview questions

epilogue


1. Object-oriented & process-oriented understanding (simple understanding is enough, gradually understanding)

The C language is process-oriented , focusing on the process , analyzing the steps to solve the problem, and solving the problem step by step through function calls.

C++ is based on object-oriented , focusing on objects , splitting one thing into different objects, and relying on the interaction between objects to complete. (C++ can also be mixed process-oriented & object-oriented).

 Two, class

2.1 Introduction of class 

    Only variables can be defined in the C language structure. In C++, not only variables but also functions can be defined in the structure.
for example:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

struct man
{
	char _name[10];
	int _age;

	void manitin(const char* name, int age) // 文件是cPP时不会报错,C文件会报错
	{
	}
};

int main()
{
  man z;  // 在C++自定义一个类,形成一个新的类型,同时也是类名。
  return 0;
}

2.2 Class Definition

1. struct 

// C中结构体
struct MyStruct 
{
	int a;
	int b;
	// 函数无法写入
};

// C++为了兼容C,C模式写法在C++编译器下不会报错,同时
// C++将C升级为了类,让函数可以存在于类中。
struct man
{
	int a;
	int b;
	void func(int a, int b)
	{
		;
	}
};

2. class 

class className
{
// 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号
(class is the keyword to define the class , ClassName is the name of the class, {} is the body of the class, note: the semicolon after the end of the class definition cannot be omitted .)
The contents of the class body are called members of the class :
  • Variables in a class are called attributes or member variables of the class ;
  • Functions in a class are called methods or member functions of the class .

Although there is a C struct, C++ and class are commonly used, which will be explained later. quack

There are two ways to define a class:

1. All the declarations and definitions are placed in the class body. Note : If a member function is defined in a class , the compiler may (with less code) treat it as an inline function .  

2. The class declaration is placed in the .h file, and the member function definition is placed in the .cpp file. Note: the member function name needs to be preceded by class name ::function name (namespace namespace, the same is true, space name:: member name)— ————— (When we complete a large project, this is more recommended, the declaration is separated from the function definition file, and the structure is clearer)

2.3 Encapsulation & Class Access Qualifiers 

1. Packaging concept

The three major characteristics of object-oriented: encapsulation, inheritance, and polymorphism. 

Encapsulation: organically combine the data and the method of manipulating the data, hide the properties and implementation details of the object, and only expose the interface to interact with the object.

Just like a computer, it is encapsulated by a metal shell on the outside, hiding the internal implementation details, and only providing power on and off, mouse and keyboard jacks, etc., so that users can interact with the computer .

Encapsulation in the C++ language can organically combine data and methods of manipulating data through classes, hide internal implementation details of objects through access rights, and control which methods can be directly used outside the class .
    And computer encapsulation requires a shell, so code encapsulation has class access qualifiers.

2. Class access qualifiers 

 

【Description of Access Qualifier】
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 rights The scope starts from the position where the access qualifier appears until the next access qualifier appears . If there is no access qualifier behind, the scope ends at }, that is, the class ends.
4. The default access right of class is private, and struct is public (because struct must be compatible with C)—here we can see that C language is relatively free, and you can insert it if you want

The basic usage is as follows:

class man  // 默认private
{
private:  // 这一句可以不写——不允许类外部直接访问
	int a;
	int b;

public:   // 从这里开始允许类外部直接访问
	void func(int a, int b)
	{
		cout << a + b << endl;
	}
};

int main()
{
	man k;
	k.func(1, 2);
	//k.a; // 报错:不可访问
	return 0;
}

Note: Access qualifiers are only useful at compile time , when the data is mapped to memory, there is no difference in access qualifiers.

2.4 Scope of classes

    A class defines a new scope , and all members of the class are in the scope of the class . When defining members outside the class , you need to use the :: scope operator to indicate which class domain the member belongs to.

class man  // 默认private
{
private:  // 这一句可以不写——不允许类外部直接访问
	int a;
	int b;

public:   // 从这里开始允许类外部直接访问
	void func(int a, int b);
};

void man::func(int a, int b)
{
	cout << a + b << endl;
}

2. 5 class object model

1. Calculate the class size

class man
{
	int age;
public:
	void func()
	{
		;
	}
};
class A
{
public:
	void A1()
	{
		;
	}
};
int main()
{
	cout << sizeof(man) << endl;  // 4字节,可见类成员函数并不存在于类中
	cout << sizeof(A) << endl;    // 没有成员变量的类,给1个字节,表示存在这个类对象。
	return 0;
}

2. The storage method of class objects

 Let's test the following code to see if our VS2019 compiler is in this way?

class man
{
	int age;
public:
	void func()
	{
		;
	}
};

int main()
{
	man a;
	man b;
	man c;
	a.func();
	b.func();
	c.func();
	return 0;

 Then we look at the disassembly.

 

We will find three instances where the same function is called .

Let's explain it directly here. During compilation, the address of the public code area where the class member function is located can be found according to the function name , and there is no need to wait until the linking period to find the filling address.

Here is a code to verify the above conclusion, as follows:

class man
{
	int age;
public:
	void func()
	{
		;
	}
};

int main()
{
	man* k = nullptr;
	k->func();
	return 0;
}

 

  

 It can be seen that the results in the two debugging information formats can be seen:

  • 1. For different class instances, the internal functions of the class they call are the same and stored in the common code area.
  • 2. The function inside the class may be an inline function. During compilation, the calling function is expanded directly.

Summary: Class member functions have these two situations 

2.6 Structure memory alignment rules

  • 1. The first member is at the address at offset 0 from the structure.
  • 2. Other member variables should be aligned to an address that is an integer multiple of a certain number (alignment number). (Note: Alignment = the smaller value of the compiler's default alignment and the size of the member. The default alignment in VS is 8)
  • 3. The total size of the structure is: an integer multiple of the maximum alignment number (the largest of all variable types and the smallest default alignment parameter).
  • 4. If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment, and the overall size of the structure is the integer of all maximum alignments (including the alignment of the nested structure) times.
  • If you still don’t know much about it, please check this  detailed explanation of structure, enumeration, and union error-prone points in C language.

 2. 7 this pointer

        Let's look at the following code:

class man
{
	int _age;
	int _tall;

public:
	void manInit(int age, int tall)
	{
		_age = age;
		_tall = tall;
	}
};

int main()
{
	man li;
	man ikun;

	li.manInit(20, 165);
	ikun.manInit(25, 180);
	return 0;
}

We know that the code of the same class function is placed in the public code area , we initialize li, and then initialize ikun, the same function is _age = age;
        _tall = tall; can't help but think, ikun Will the initialization of li overwrite the data of li ? ?

It is indeed such a low-level error. Scientists thought of this value pointer. C++ solves this problem by introducing this pointer, that is: C++ compiler adds a hidden pointer parameter to each "non-static member function", so that the pointer Points to the current object (the object that calls the function when the function is running), and all "member variable" operations in the function body are accessed through this pointer. It's just that all operations are transparent to the user, that is, the user does not need to pass it, and the compiler completes it automatically .

 After completion, it will look like this, but an error will be reported:

class man
{
	int _age;
	int _tall;

public:
	void manInit(man* const this ,int age, int tall) // 编译器会自动添加一个不可修改指向的this指针,不允许人为添加
		                                             // 这样就解决了找不到对象的问题。
	{
		cout << this << endl;  // 无法修改但可以读
		this->_age = age;      // 自动隐式添加
		this->_tall = tall;    // 自动隐式添加,这里只是人为显示
	}
};

int main()
{
	man li;
	man ikun;

	li.manInit(&li ,20, 165);
	ikun.manInit(&ikun, 25, 180);
	return 0;
}

1. This pointer characteristics

  • The type of this pointer: class type * const, that is, in member functions, the this pointer cannot be assigned a value.
  • Can only be used inside a "member function".
  • 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.
  • 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. (possibly via the stack)

2. This pointer interview questions

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

 The result is C. Normal operation . Analysis: This is similar to the previous question, print() is a class member function, and the code is short, it is treated as an inline function, the call site is replaced during compilation, and p is not dereferenced.

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

 The result is that B. Run crashes. Analysis: print() is a class member function, which is treated as an inline function. It replaces the call site during compilation, and passes nullptr to this pointer at the same time, and dereferences this (nullptr) later, so it crashes.

epilogue

This section is over here, thank you friends for browsing, if you have any suggestions, welcome to comment in the comment area, if you bring some gains to your friends, please leave your likes, your likes and concerns will become bloggers The driving force of the master's creation.

Guess you like

Origin blog.csdn.net/qq_72112924/article/details/130487684