(c++) Classes and Objects Part 1

Table of contents

1. Preliminary understanding of process-oriented and object-oriented

2. Introduction of classes

3. Class definition

4. Class access qualifiers and encapsulation

5. Scope of class

6. Instantiation of classes

7. Calculation of class object size

8. This pointer of class member function


  • C language is process-oriented , focusing on the process , analyzing the steps to solve the problem, and gradually solving the problem through function calls.
  • C++ is based on object-oriented and focuses on objects . It splits one thing into different objects and relies on the interaction between objects. Why is C++ based on an object-oriented language? Because C++ can not only be object-oriented, but also process-oriented, which is considered a hybrid. Secondly, C++ must be compatible with the C language.
Little knowledge: Java is a purely object-oriented language.

         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: if a stack is implemented in C language, only variables can be defined in the structure ; now if it is implemented in C++ , you will find that functions can also be defined in the struct .
  • c language implementation stack:
statement:
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDateType;

typedef struct Stack
{
	STDateType* arr;
	int top;
	int capacity;
}ST;

void StackInit(ST* ps);//初始化

void StackDestory(ST* ps);//销毁

void StackPush(ST* ps, STDateType x);//压栈

void StackPop(ST* ps);//出栈

STDateType StackTop(ST* ps);//取栈顶元素

bool StackEmpty(ST* ps);//判断栈是否为空

int StackSize(ST* ps);//获取栈元素个数

accomplish:
#include"Stack.h"

void StackInit(ST* ps)//初始化
{
	assert(ps);
	ps->arr = NULL;
	ps->top = 0;
	ps->capacity = 0;

}

void StackDestory(ST* ps)//销毁
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

void StackPush(ST* ps, STDateType x)//压栈
{
	assert(ps);
	if (ps->top == ps->capacity) //扩容
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDateType* tmp = (STDateType*)realloc(ps->arr, sizeof(STDateType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc");
			exit(-1);
		}

		ps->arr = tmp;
		ps->capacity = newCapacity;
	}

	ps->arr[ps->top] = x;//尾插
	ps->top++;
}

void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

STDateType StackTop(ST* ps)//取栈顶元素
{
	assert(ps);
	assert(!StackEmpty(ps));//ps->top != 0
	
	return ps->arr[ps->top - 1];
}

bool StackEmpty(ST* ps)//判断栈是否为空
{
	assert(ps);

	return ps->top == 0;

}

int StackSize(ST* ps)//获取栈元素个数
{
	assert(ps);

	return ps->top;
}

  • c++ implementation stack:
typedef int DataType;
struct Stack
{
   void Init(size_t capacity)
   {
      _array = (DataType*)malloc(sizeof(DataType) * capacity);
      if (nullptr == _array)
      {
         perror("malloc申请空间失败");
          return;
      }
      _capacity = capacity;
      _size = 0;
    }

    void Push(const DataType& data)
    {
        // 扩容
        _array[_size] = data;
        ++_size;
    }

    DataType Top()
    {
        return _array[_size - 1];
     }

     void Destroy()
     {
         if (_array)
         {
             free(_array);
             _array = nullptr;
             _capacity = 0;
             _size = 0;
         }
     }

     DataType* _array;
     size_t _capacity;
     size_t _size;
};

Little knowledge: The definition of the structure above is preferred to be replaced by class in C++


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

  • The contents in 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
Two ways to define classes:
1. All declarations and definitions are placed in the class body. Please note: if a member function is defined in a class , the compiler may 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 class name needs to be added before the member function name::

Quick tip: The class name also represents the type. example:


4.1 Access qualifiers
The way C++ implements encapsulation: use classes to combine the properties and methods of objects to make the objects more complete, and select them through access rights.
Selectively provide its interface to external users .

 

[Access Qualifier Description]
  • Members modified by public can be directly accessed outside the class

  • Protected and private modified members cannot be directly accessed outside the class ( protected and private are similar here )

  • The access scope begins at the occurrence of this access qualifier and ends at the occurrence of the next access qualifier.

  • If there is no access qualifier later, the scope ends at }, which is the end of the class.

  • The default access rights of class are private and struct is public ( because struct must be compatible with C)

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

tips:

What is the difference between struct and class in C++ ?
  •          C++ needs to be compatible with the C language, so struct in C++ can be used as a structure. In addition, struct in C++ can also be used to define classes. It is the same as class defining a class. The difference is that the default access permission of a class defined by struct is public , and the default access permission of a class defined by class is private .
The three major characteristics of object-oriented : encapsulation , inheritance, and polymorphism .
In the class and object stage, we mainly study the encapsulation characteristics of classes. So what is encapsulation?
  • Encapsulation: Organically combine data and methods of operating data, hide the properties and implementation details of the object, and only expose the interface to interact with the object.
  • Encapsulation is essentially a kind of management that makes it easier for users to use classes . For example: For a complex device like a computer, the only things provided to the user are the power on/off button, keyboard input, monitor, USB jack, etc., allowing the user to interact with the computer and complete daily tasks. But in fact, the real work of the computer is the CPU , graphics card, memory and other hardware components.
  • For computer users, there is no need to worry about the internal core components, such as how the circuits on the motherboard are laid out, how the CPU is designed internally, etc. Users only need to know how to turn on the computer and how to interact with the computer through the keyboard and mouse. . Therefore, when andcomputer so that users can interact with the computer .
  • To implement encapsulation in the C ++ language, data and methods for operating data can be organically combined through classes, and access rights can be used to hide the internal implementation details of objects and control which methods can be used directly outside the class .

A class defines a new scope , and all members of the class are within the scope of the class . When defining members outside a class, you need to use the :: scope operator to indicate which class scope the member belongs to.
class Person
{
public:
     void PrintPersonInfo();
private:
  char _name[20];
  char _gender[3];
  int  _age;
};

// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
   cout << _name << " "<< _gender << " " << _age << endl;
}


The process of creating an object from a class type is called instantiation of the class
1. A class describes an object . It is something like a model . It limits the members of the class. Defining a class does not allocate actual memory space to store it;
2. A class can instantiate multiple objects. The instantiated objects occupy actual physical space and store class member variables .
3. Make an analogy. Instantiating objects from a class is like using architectural design drawings to build a house in reality. A class is like a design drawing . It only designs what is needed, but there is no physical building. Similarly, a class is just a design that is instantiated. Objects can actually store data and occupy physical space.


     7.1 Guessing the storage method of class objects
  • The object contains the individual members of the class

Defect: The member variables in each object are different, but the same function is called. If it is stored in this way, when one
When a class creates multiple objects, a copy of the code will be saved in each object. The same code is saved multiple times, which wastes space.

  • Only one copy of the code is saved, and the address where the code is stored is saved in the object.

  • Only member variables are saved, and member functions are stored in the public code section.
                

 

 Compilers generally adopt the third method for storage: testing

7.2 Class size

The size of a class is actually the sum of the " member variables " in the class. Member functions do not enter the class, so they do not occupy the size of the class space. Member variables follow memory alignment rules. In addition, pay attention to the size of empty classes. Empty classes are special. The compiler gives the empty class a byte to uniquely identify objects of this class

 Regarding memory alignment:

1. The first member is at the address offset 0 from the structure.
2. Other member variables should be aligned to addresses that are integer multiples of a certain number (alignment number).
Note: Alignment number = the smaller of the compiler's default alignment number and the size of the member.
The default alignment number 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 and the nested structure is aligned to an integer multiple of its own maximum alignment number, the overall size of the structure is an integer of all maximum alignment numbers (including the alignment number of nested structures) times.

See also this structure memory alignment .


class Date
{
public:
	void Init(int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << _year << "." << _month << "." << _day << endl;
	}

private:
	int _year;  //声明
	int _month;
	int _day;
};

int main()
{
	Date d1, d2;

	d1.Init(2023, 9, 1);
	d1.Print();

	d2.Init(2023, 9, 2);
	d2.Print();
	return 0;
}

For the above class, there is such a problem:
There are two member functions, Init and Print , in the Date class . There is no distinction between different objects in the function body. So when d1 calls the Init function, how does the function know that it should set the d1 object instead of the d2 object?

C++ solves this problem by introducing the this pointer, that is: the C++ compiler adds a hidden pointer parameter to each " non-static member function " , allowing the pointer to point to the current object ( the object that calls the function when the function is running ) . All operations on " member variables " 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, the compiler automatically completes it .

 Characteristics of this pointer
  •  The type of this pointer: class type * const , that is, in member functions, 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 to the this parameter as an actual parameter. Therefore, 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.
example:
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
	void Print()
	{
		cout << this << endl;
		cout << "Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();  
	return 0;
}

Answer: It runs normally because the function is in the public code area. Although the pointer calls this function, the pointer is not decoded.

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

Answer: The run crashed because of a null pointer problem. The null pointer was dereferenced.

Where is the this pointer stored?
  • The storage location of this is in the stack area, because this pointer is a formal parameter, and formal parameters are generally stored in the stack area.
  • But this pointer may also be optimized - vs is put into a register, so the specific storage location depends on the compiler

Note: Conceptual content comes from Bit Technology

Guess you like

Origin blog.csdn.net/m0_73969113/article/details/132476178