C + + learning record 2 -- classes and objects

Posted by jacobsdad on Tue, 25 Jan 2022 18:17:01 +0100

1, Classes and objects

1. Class and object concepts

Everything is an object with attributes and methods.
Objects with the same properties and methods (the same properties) can be abstracted as classes.

Properties and objects in a class are collectively referred to as members
Attributes are also called member attributes, and member variables are also called field s; Methods are also called member methods, member functions.

2. Definition of classes and objects

const double PI = 3.14;
class Circle
{
   public:  //Public permission (if not written, the default is private)
     int r;  //Attribute: radius of circle (variable)
     double calculateS()  //Method: find the circumference of the circle (function)
     {
     	return 2*PI*r;
     }
};

int main()
{
	//Through the circle class, create a specific circle object (instantiation)
	Circle c1;
	//Assign values to the attributes of the circle object
	c1.r = 10;
	cout<<"The circumference of the circle is:"<<c1.calculateS()<<endl;

Methods in the same class can be called directly, and class names should be used for different classes method

3. The difference between struct and class

The only difference is that the default access rights are different

  • The default permission of struct is public
  • class default permission is private

2, Encapsulation

1. Significance of packaging

  • Show the properties and methods as a whole, hide the implementation details, and call directly
class Circle
{
   public: 
     int r;  //Attribute: radius of circle (variable)
     double calculateS()  //Method: find the circumference of the circle (function)
     {
     	return 2*PI*r;
     }
     void getR(int R)  //The attribute can be assigned by method
     {
     	r = R;
     }
};
  • Control the attributes and behaviors to ensure safety

Access rights:

There are three kinds of access rights:
1.public - public permission (both inside and outside the member class can be accessed)
2.protected -- protected permission (accessible within member class, inaccessible outside class, accessible by subclass)
3.private - private permission (members can be accessed within the class, not outside the class, and subclasses cannot be accessed)

class Person
{
   public: 
     string name; 
   protected:
     int age;
   private:
     int password;
   private:
     void put()  //Accessible within the class
     {
     	name = "Zhang San";
     	age = 20;
     	password = 123456;
     }
};

int main()
{
	Person P1;
	//P1.age = 10;  // Not accessible outside class
	//P1.put(); 

Privatization of member properties:

advantage:

  1. Set all member properties as private, and you can control the read and write permissions yourself
  2. For write permission, the validity of data can be detected
class Person
{
  private:
     string m_name;  //read-only
     int m_age;  //Readable and writable
     int m_password;
  public:  //Operate through public interface
     string getName()  //Get private properties through public functions
     {
     	return m_name;
     }
     void setAge(int age)  //Modifying private properties through public functions
     {
     	if (age<0)  //Judge the validity of test data
     	{
     		cout<<"You piece of skin"<<endl;
     		return;
     	}
     	if (age>150)
     	{
     		cout<<"You old goblin"<<endl;
     		return;
     	}
     	else 
     	{
     		m_age = age;
     	}
     }
     int getAge()
     {
     	return m_age;
     }
};

int main()
{
	Person P1;
	setAge(200);
	getAge();
}	

Scope operator:

Two colons:
Create the class Point in the header file and include it in the source file. Calling the function in the Point class needs to indicate the scope with the scope operator.

#include "point.h"

int Point::getX()  //Indicates that it is the getX() function under the scope of coin
{
	return X;
}

3, Object initialization and cleanup

Each object has initial settings and cleanup data settings before object destruction

1. Constructor and destructor

If the object is not initialized, the use consequence is unknown; If it is not cleaned in time, there may be safety problems
There are constructors and destructors in C + +, which will be automatically called by the compiler to complete object initialization and cleaning. If we do not provide constructs and destructs, the compiler will provide (mandatory), but the constructs and destructs provided by the compiler are empty implementations (there is no code in the function).

  • Constructor (also known as constructor or constructor): its main function is to assign value to the object member attribute when creating the object and call it automatically
  • Destructor: the system will automatically call before the object is destroyed to perform some cleaning work

Constructor syntax: class name () {}

  1. No return value nor write void
  2. The function name is the same as the class name
  3. Constructors have parameters, so overloading can occur
  4. When the program calls the object, it will automatically call the construction without manual call, and only call it once

Destructor syntax: ~ class name () {}

  1. No return value nor write void
  2. The function name is the same as the class name, and the ~ sign is added before the name
  3. Destructors cannot have parameters and cannot be overloaded
  4. The program will automatically call the destructor before the object is destroyed without manual call, and only call it once
class Person
{
public:  //Public is required to call
	Person()
	{
		cout<<"Call to constructor"<<endl;
	}
	~Person()
	{
		cout<<"Call of destructor"<<endl;
	}
};

void test1()
{
	Person P1;  //The data on the stack will be released (destroyed) after test1 is executed
}
int main()
{
	test1();  //Creating an object automatically calls Person()
	          //Automatically call ~ Person() after test1 is executed
	Person P2;  //Call only Person()
				//After the main() function is executed, ~ Person() will be called
}	

2. Classification and calling of constructors

Two classification methods:

  • Divided into parametric construction and nonparametric construction by parameters (default)
  • By type, it can be divided into ordinary structure and copy structure

Three call modes:

  • bracketing
  • Display method
  • Implicit transformation method

The copy structure has parameters, and the parameters are another class. Copy all the attributes of another class to this class
const needs to be added to prevent changing the original class, and reference passing needs to be used

class Person
{
	int age;
public:  
	Person(const Person01 &p)
	{
		cout<<"Call of copy constructor"<<endl;
		age = p.age;
	}
};
void test1()
{
	//1. Bracket method
	Person P1;  //Call the default constructor without adding (), otherwise it will be considered as the declaration of the function
	Preson P2(10);  //Call parameterized constructor
	Person P3(P2);  //Call copy constructor

	//2. Display method
	Person P1;
	Person P2 = Person(10);
	Person P3 = Person(P2);

	//3. Implicit transformation method
	Person P2 = 10;  //Equivalent to Person P2 = Person(10);
	Person P3 = P2;
}
int main()
{
	test1();  
}	

PS:

  1. Person(10) is an anonymous object, Person P2 = Person(10); Named P2
    Characteristics of anonymous objects: after the execution of the current line, the system will immediately recycle the anonymous objects
  2. Do not initialize anonymous objects with copy constructors
    Person(P3) will be considered by the compiler as Person P3 / / (object declaration)

3. Call timing of copy constructor

There are usually three situations:

  1. Initialize a new object with a created object (most commonly used)
  2. The method of value transfer is to transfer values to function parameters (equivalent to creating a temporary copy)
class Person
{
	int age;
};
void dowork(Person p)  //pass by value
{
}
int mian()
{
	Person P;
	dowork(P);
}
  1. Returns a local object as a value
class Person
{
	int age;
};
Person dowork1()  //Local object
{
	Person P1;  //P1 is released after execution
	return P1;  //Copy a new object (P1 ') and return it to p
}
int mian()
{
	Person p = dowork1();  //p is not P1, it is P1 '
}

4. Calling rules of constructor

By default, the C + + compiler adds at least three functions to a class:
1. Default constructor 2 Default destructor 3 The default copy constructor copies the value of the attribute

Call rule:
1. If the user defines a parameter constructor, C + + no longer provides the default parameter free construction, but provides the default copy construction
2. If the user defines a copy constructor, C + + no longer provides other constructors

class Person
{
	int age;
public:  
	Person(int age1)  //There is already a parameter constructor
	{
		cout<<"Call with parameter constructor"<<endl;
		age = age1;
	}
};
int mian()
{
	//Person P;  // An error is reported. There is no default constructor to call
	Person P(10);
}

5. Deep copy and shallow copy

Shallow copy: a simple assignment copy operation
Deep copy: reapply space in the heap area for copy operation

class Person
{
public:
	Person()
	{
		cout << "Default constructor " << endl;
	}
	Person(int age,int height)
	{
		m_age = age;
		m_height = new int(height);
		cout << "Parameterized constructor" << endl;
	}
	~Person()
	{
		//Destruct code to release heap data
		if (m_height != NULL)
		{
			delete m_height;
			m_height = NULL;
		}
		cout << "Default destructor" << endl;
	}
	int m_age;
	int* m_height;
};

void test1()
{
	Person P1(18,180);
	cout << "P1 Age:" << P1.m_age <<"Height:"<<P1.m_height<< endl;
	Person P2(P1);
	cout << "P1 Age:" << P1.m_age << "Height:" << P1.m_height << endl;
}

int main()
{
	test1();
	return 0;
}

The above code execution will report an error because the destructor code is executed twice to release space repeatedly

Solution: re open up space through deep copy

Person(const Person &p)
	{
		m_age =p.m_age;
		//m_height = p.m_height;  // Compiler default implementation
		//Deep copy
		m_height = new int(*p.m_height);
		cout << "copy constructor " << endl;
	}

6. Initialization list

Property constructor () for initializing object: Property 1 (value 1),... {}

class Person
{
	int age1;
	int age2;
};
Person():age1(10),age2(20)
{

}
int main()
{
	Person p;
}

or

class Person
{
	int age1;
	int age2;
};
Person(int a,int b):age1(a),age2(b)
{

}
int main()
{
	Person p(20,10);
}

7. Class objects as class members

A member in a class can be an object of another class, which is called an object member

class A 
{
public:
	setA()
	{
		A a;
	}
};
class B
{
	int n;
	A a;  //Object member
};

When the objects of other classes are members of this class, the class object is constructed first, and then the class object is constructed. When destructing, the class object is destructed first, and then the class object is destructed

8. Static members

Add static before member variable and member function
Static member variables:
All objects share the same data, allocate memory in the compilation stage, declare within the class and initialize outside the class
Static member function:
All objects share the same function, and static member functions can only access static member variables
Static member functions also have access

class Person
{
public:
	static void fun()
	{
		a=10;
		//b=10;  // error
	}
	static int a;
	int b;  //It belongs to a specific object, and the static function call cannot distinguish which object belongs to b
};

int a = 0;
int main()
{
	Person p;  //Access by object
	p.fun();  //Out of class initialization

	Person::fun();  //Accessed by class name, it can be accessed without creating an object
}

4, C + + object model and this pointer

1. Member variables and member functions are stored separately

In class member variables and member functions are stored separately. Only non static member variables belong to the object of the class

Memory space occupied by empty class and object: 1 byte
The compiler will allocate 1 byte space to each empty object to distinguish the memory occupied by empty objects. Each empty object also has a unique memory address.

class Person
{
public:
	 void fun()  //(static / non static) member function on an object that does not belong to a class
	{}
	static int a;  //Static member variable, on an object that does not belong to a class
	int b;  //There are only non static member variables on objects belonging to classes
};
int Person::b=0;  //Out of class initialization
int main()
{
	Person p;  
}

The space occupied by the above Person p is 4 bytes (only int b)

2.this pointer

Each non static member function will only produce a function instance, and multiple objects of the same type will share a piece of code.
C + + provides a special object pointer: this pointer, which points to the object to which the called member function belongs
this pointer is implicit in each non static member function and can be used directly without definition

The essence of this pointer is a pointer constant, which cannot be modified

Purpose:

  • When a formal parameter has the same name as a member variable, it can be distinguished by this pointer
class Person
{
public:
	Person(int age)  //The first three age s will be considered the same quantity
	{
		age = age;  //Output garbled code
		this->age = age;  //Correct, this age is the same as the following int age
	}
	int age; 
	int m_age;  //Distinguished variable name, member age
};
int main()
{
	Person p1(18);
	cout << "p1 Age:" << p1.age << endl;
}
  • Return the object itself in the non static member function of the class. You can use return * this
class Person
{
public:
	Person(int age)
	{
		this->age = age;
	}

	Person& PersonAge(Person& p)  //If returned by reference, p2 will always be returned, and a new temporary object will be created by value
	{
		this->age += p.age;
		return *this;
	}
	int age;
};

void test1()
{
	Person p1(10);
	Person p2(20);
	//Chain programming idea, which can be realized by returning p2 every time
	p2.PersonAge(p1).PersonAge(p1).PersonAge(p1);  //Value passing cannot be implemented
}
int main()
{
	test1();
	return 0;
}

PS:
p2.PersonAge(p1).PersonAge(p1).PersonAge(p1); Such a chain programming idea of continuous addition and cout < < a = "< < a < < endl; Are essentially the same
The implementation needs to return the value to itself every time (p2/cout)

3. Null pointer accessing member function

Null pointers can also call member functions, but pay attention to whether this pointer is used. If this pointer is used, it is usually judged to ensure the robustness of the code.

class Person
{
public:
	void getage()
	{
		if (this ==NULL)  //Prevent pointer from being null
			return;
	//m_age is this - > M_ The incoming pointer cannot be null
		cout << "age:" << m_age << endl;
	}
	int m_age;
};
void test2()
{
	Person* p = NULL;
	p->getage();//An error is reported because a null pointer is passed in and the property m cannot be accessed_ age()
}
int main()
{
	//test1();
	return 0;
}

4.const decorated member function

A member function is called a constant function after being modified with const. The member attribute cannot be modified in a constant function. After adding the keyword mutable when declaring the member attribute, it can still be modified in the constant function and under the constant object

const before declaring an object is called a constant object. A constant object can only call constant functions (ordinary member functions may modify properties)

class Person
{
public:
	void getage() const
	{
		this->m_age=10;  //Add const and cannot be modified
		cout << "age:" << m_age << endl;
	}
	int m_age;
	//mutable int m_age;  // Mutable can be modified
};

Topics: C C++ Back-end