C + + classes and objects

Keywords: C++ Back-end

A change of blogger (thanks for reading): at first, blogging was just a whim. It was just to help review the knowledge points. I'm glad that my blog can be liked by everyone. However, recently, I deeply feel that writing a long blog is really too tired, and I have received a lot of feedback from fans during this period. It is suggested to pick some difficulties to write a blog. After thinking over and over again, the blogger decided to adopt everyone's suggestions, so the next blog will not list all the relevant knowledge points "in detail ", but will choose some knowledge points that bloggers think are worthy of analysis for sharing. Many relatively simple basic knowledge points believe that readers can read relevant books directly.

This paper will introduce this pointer in class object, "why can't copy constructor be passed by value?" and "const permission scaling problem".

1.this pointer

Looking back, we passed C language implementation stack Some function declarations used when

Function declaration for stack operation:

void StackPush(ST* ps,STDataType elem);

Function declaration for out of stack operation

void StackPop(ST* ps);

Stack destruction function declaration

void StackDestroy(ST* ps);

During the implementation of stack functions, no matter which function we are implementing, we must pass a "stack pointer" to ensure the smooth implementation of subsequent processes.

Then, in the class objects extended by C + +, do you still need to pass the "stack pointer" like this?

for instance:

class Date
{
public:
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	void SetDate(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	};
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date a1, a2;
	a1.SetDate(2000, 5, 12);
	a2.SetDate(2006, 6, 19);
	a1.Display();
	a2.Display();

	return 0;
}

In the above example, there are two member functions of Display and SetDate in the Date class. There is no distinction between different objects in the function body. When a1 calls the SetDate function, how does the function know whether we want to set s1 or s2???

The answer is the this pointer

In fact, when we call the function, the system has quietly helped us convert. In the above example, when we call display, the compiler will implicitly pass a Date * pointer to display, that is, the actual parameter is A1. Display (& A1). When defining display, the compiler will also implicitly pass a Date * pointer

This implicitly passed pointer is the this pointer. Its essence is the formal parameter of a member function, which is automatically passed by the compiler through the ecx register.

This pointer is only a hidden pointer parameter assigned by the cpp compiler to the "non static member function". Pay attention! Pay attention!! it is a non static member function, and the static member function modified by static has no this pointer!

this pointer related surface

1. Which area of memory does this pointer exist in?

Since this pointer is essentially a formal parameter of a member function, it is naturally a stack area stored in memory!

2. Can this pointer be null?

Yes, but for details, please see the following code:

class A
{
public:
	void PrintA()
	{
		cout<<_a<<endl;
	}
	void Show()
	{
		cout<<"Show()"<<endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
    p->PrintA(); //Operation 1
	p->Show();  //Operation 2
}

Result: when PrintA() is called, it crashes, and when Show() is called, it runs smoothly

analysis:

1. When calling PrintA, this pointer accesses _a. the essence of accessing the member value is this - > member, but p is empty and passed to this. As a result, this is also nullptr, but the null pointer cannot access its member! So the program crashes.

2. When calling the show member function, you will not deliberately access the space pointed to by P, so there is no problem of null pointer dereference! Just simply pass p to the this pointer, but the member function does not dereference the this pointer! Oh! No! (the address of the member function is not stored in the object, but in the public code segment)

2. Copy constructor

2.1 why can't I call by value?

Take the date class as an example:

class Date
{
public:
	Date(int year=1943,int month=8,int day=8)
	{
		_year = year;
		_month = month;
		_day = day;
	}
    //×, Pass value call copy construction, infinite recursion
	Date(const Date d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
    Date d1;
    Date d2(d1);
    return 0;
}

Using the value passing method will cause infinite recursive calls

How to solve it?

Pass reference and call copy structure (in fact, passing pointer is OK, but it is not necessary. The reference efficiency is higher and one copy is missing)

Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

2.2 since there is a default copy structure, does it not need to write a copy constructor?

This is true for the date class, but look at the Stack class:

class Stack
{
public:
	Stack(int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int)*capacity);
		if (_a == nullptr)
		{
			cout << "malloc fail" << endl;
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}

	~Stack()
	{
		// For a class like Stack, the destructor is used to clean up the resources in the object
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}

private:
	// Similar to the constructor, we do not write it. The compiler generates the constructor by default and does eccentric processing:
	// 1. Built in type members are not processed
	// 2. A custom type member will call its destructor
	int* _a;
	int _top;
	int _capacity;
};


int main()
{
	Stack st1;
	Stack st2(st1);

	return 0;
}

Running the program directly will crash, because when defining the object for the first time, the constructor is called to open up a space in the heap area, but when defining the object for the second time, the copy structure is called, that is, no space is opened this time (the copy structure uses passing reference! Passing reference! Remember passing reference! Just mentioned earlier) , but directly copy the contents of st1 to st2, then the members of st1 and st2 point to the same space, but st2 will destruct first to release the space, and then st1 will destruct, but the same space cannot be destructed twice, so the program crashes.

3. Const permission scaling

class Date
{
public:
    void print()
    {
        cout << "day:" << _day << endl;
    }
private:
    int _day;
};

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

    const Date d2;
    d2.print();

    return 0;
}

The compiler indicates that d2 has an error, so what's wrong with d2?

This is the problem of const permission scaling. We know that the type of d2 is const Date, so when d2 calls the print function, the system will pass a this pointer to print. The type of this pointer is Date *, but the address type of d2 is const Date *. Passing a const modified pointer to an ordinary pointer will expand the permission. Expanding the permission is not allowed!!!

The solution is to introduce the member function of const modifier class

The class member function modified by const is called const member function. Const modifies the class member function and actually modifies the implicit this pointer of the member function (note Oh! Note Oh! Only modify the formal parameter of this pointer), indicating that no member of the class can be modified in the member function.

class Date
{
public:
    void print() const//The essence is the this pointer that modifies the formal parameter list
    {
        cout << "day:" << _day << endl;
    }
private:
    int _day;
};

const four questions

1. Can const objects call non const member functions?

A: No, the permission cannot be enlarged

Can non const objects call const member functions?

A: Yes, the permission can be reduced. For example, d1 can still call the member function of const modifier class

3. Can other non const member functions be called in const member functions?

A: No, as long as you call the member function, you must pass the this pointer, but if the function modified by const calls the unmodified function, the permission will be expanded

4. Can other const member functions be called in non const member functions?

A: Yes, the permission can be reduced

Thank you for reading!!! If the content is helpful to you, remember to give me Sanlian (praise, collection and attention) - be a person with lingering fragrance.

Posted by FrOzeN on Wed, 03 Nov 2021 23:23:47 -0700