Static member
Type preceded by static
Static member variable
All objects share the same data
Allocate memory at compile time and declare in class
Out of class initialization
Static member function
All objects share the same function
Static member functions can only access static member variables
Private permissions are also inaccessible
C + + object model and this pointer
Member variables and member functions are stored separately
Member variables and member functions in a class are stored separately. Only non static member variables belong to the object of the class
Non static member variables occupy object space
Static member variables do not occupy object space
Member functions (static / non static) also do not occupy object space
this pointer concept
Each non static member function will only produce a function instance, that is, multiple objects of the same type will share a piece of code
So the question is: how does this piece of code distinguish that object from calling itself?
c + + solves the above problems by providing special object pointer and this pointer. The this pointer points to the object to which the called member function belongs
this pointer is a pointer implied in each non static member function
this pointer does not need to be defined and can be used directly
Purpose of this pointer:
When a formal parameter has the same name as a member variable, it can be distinguished by the this pointer
Return the object itself in the non static member function of the class. You can use return *this
Null pointer access member function
C + + hollow pointer can also call member functions, but pay attention to whether this pointer is used
If this pointer is used, it needs to be judged to ensure the robustness of the code
if (this == NULL) { return;
const modifier member function
Constant function:
After adding const to a member function, we call this function a constant function
Member properties cannot be modified within a constant function
After the keyword mutable is added to the member attribute declaration, it can still be modified in the constant function
The object data pointed to by this pointer can be modified
void ShowPerson() const { //const Type* const pointer; //this = NULL; // The pointer pointing to Person* const this cannot be modified; //this->mA = 100; // However, the data of the object pointed to by this pointer can be modified //const modifies the member function, indicating that the data in the memory space pointed to by the pointer cannot be modified, except for mutable modified variables this->m_B = 100; }
Constant object:
Add const before declaring an object to call it a constant object
Constant objects can only call constant functions
public: int m_A; mutable int m_B; //Modifiable variable
Friends
The purpose of a friend is to let a function or class access private members in another class
Just declare it before, function / class
friend class goodGay; friend void goodGay(Building * building);
The keyword of friend is friend
Three implementations of friends
Global function as friend
Class as friend
Member function as friend
Operator overloading
Plus operator overload
Person operator+(const Person& p) { Person temp; temp.m_A = this->m_A + p.m_A; temp.m_B = this->m_B + p.m_B; return temp; } Person p3 = p2 + p1; //Equivalent to P2 operaor+(p1) //function overloading Person operator+(const Person& p2, int val) { Person temp; temp.m_A = p2.m_A + val; temp.m_B = p2.m_B + val; return temp; } Person p4 = p3 + 10; //Equivalent to operator+(p3,10)
For expressions with built-in data types, the operator cannot be changed
Do not abuse operator overloading
Shift left operator overload
Overloading the shift left operator with friends can output user-defined data types
ostream& operator<<(ostream& out, Person& p) { out << "a:" << p.m_A << " b:" << p.m_B; return out; } Person p1(10, 20); cout << p1 << "hello world" << endl; //Chain programming
Increment operator overload
Realize your own integer data by overloading the increment operator
//Front++ MyInteger& operator++() { //First++ m_Num++; //Return again return *this; } //Post++ MyInteger operator++(int) { //Return first MyInteger temp = *this; //Record the current value of itself, and then add 1 to the value of itself, but the previous value is returned. Return first and then + +; m_Num++; return temp; }
The pre increment returns a reference and the post increment returns a value
Assignment operator overload
The c + + compiler adds at least four functions to a class
Default constructor (no parameters, empty function body)
Default destructor (no parameters, empty function body)
The default copy constructor copies the values of attributes
The assignment operator operator =, copies the value of the attribute
If an attribute in the class points to the heap, the deep and shallow copy problem will also occur during assignment
Person& operator=(Person &p) { if (m_Age != NULL) { delete m_Age; m_Age = NULL; } //The code provided by the compiler is a shallow copy //m_Age = p.m_Age; //Provide deep copy to solve the problem of shallow copy m_Age = new int(*p.m_Age); //Return to itself return *this; }
Relational operator overloading
Overloaded relational operators allow two custom type objects to be compared
bool operator==(Person & p) { if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) { return true; } else { return false; } } bool operator!=(Person & p) { if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) { return false; } else { return true; } }
Function call operator overloading
function call operator () It can also be overloaded Because the method used after overloading is very similar to the call of a function, it is called an imitation function Imitation function has no fixed writing method and is very flexible
void operator()(string text) { cout << text << endl; } //Anonymous object call cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
Anonymous function calls can also be used without initialization
inherit
·Inheritance is one of the three characteristics of object-oriented. There is a special relationship between some classes
·When defining these classes, the members of the lower level have their own characteristics in addition to the commonalities of the upper level.
·At this time, we can consider using inheritance technology to reduce duplicate code
Basic syntax of inheritance
//Public page class BasePage { public: void header() { cout << "Home page, open class, login, registration...(Common head)" << endl; } }; //Java page class Java : public BasePage { public: void content() { cout << "JAVA Subject video" << endl; } };
Inherited advantages
You can reduce duplicate code
class A : public B;
Class A is called a subclass or derived class
Class B is called a parent or base class
Members in derived classes consist of two parts:
One class is inherited from the base class, and the other is a member added by itself.
Inherited from the base class shows its commonness, while the new members reflect its individuality.
Inheritance mode
When public inherits, the members of the public type in the parent class will be inherited into the public of the child class, and the protected members of the parent class will also be inherited into the protected of the child class
When protected inherits, both public and protected members of the parent class will be inherited into the protected of the child class
When private inherits, the public and protected members of the parent class will be inherited into the private of the child class
class Son3:private Base3 { public: void func() { m_A; //Access to private rights m_B; //Access to private rights //m_C; // Inaccessible } }; class GrandSon3 :public Son3 { public: void func() { //Son3 is a private inheritance, so the properties of inherited son3 cannot be accessed in GrandSon3 //m_A; //m_B; //m_C; } };
Object model in inheritance
Which members inherited from the parent class belong to the subclass object
Private members are just hidden, but they will inherit
The private members in the parent class are also inherited by the child class, but can not be accessed after being hidden by the compiler
Construction and deconstruction order in inheritance
After a subclass inherits from the parent class, when a subclass object is created, the constructor of the parent class will also be called
What is the construction and deconstruction order of parent and child classes?
In inheritance, the constructor of the parent class is called first, and then the constructor of the child class is called. The deconstruction order is opposite to that of the construction
Inherit the handling of members with the same name
When a member with the same name appears in the subclass and parent class, how can you access the data with the same name in the subclass or parent class through the subclass object?
You can access the member with the same name in the subclass directly
To access a member with the same name as the parent class, you need to add a scope
When a subclass has a member function with the same name as the parent class, the subclass will hide all versions of the member function with the same name in the parent class
If you want to access a member function with the same name hidden in the parent class, you need to add the scope of the parent class
s.func();//Subclass s.Base::func();//Parent class
Inherit static member handling with the same name
Static members and non static members have the same name and are handled in the same way
Multiple inheritance syntax
C + + allows a class to inherit multiple classes
Syntax: class subclass: inheritance method parent class 1, inheritance method parent class 2
Multiple inheritance may cause members with the same name in the parent class, which needs to be distinguished by scope. Therefore, multiple inheritance is not recommended in the actual development of C + +.
class Son : public Base2, public Base1 { public: Son() { m_C = 300; m_D = 400; } public: int m_C; int m_D; };
diamond inheritance
Two derived classes inherit the same base class
Another class inherits two derived classes at the same time
This inheritance is called diamond inheritance, or diamond inheritance
Grass Mud Horse inherited animal data in two copies (sheep and camels). In fact, we should be clear that we only need one copy of this data.
The main problem caused by diamond inheritance is that subclasses inherit two copies of the same data, resulting in waste of resources and meaninglessness
The problem of diamond inheritance can be solved by virtual inheritance
class Animal { public: int m_Age; }; //After adding the virtual keyword before inheritance, it becomes virtual inheritance //At this time, the public parent class Animal is called the virtual base class class Sheep : virtual public Animal {}; class Tuo : virtual public Animal {}; class SheepTuo : public Sheep, public Tuo {};
polymorphic
Polymorphism is one of the three characteristics of C + + object-oriented
Polymorphisms fall into two categories
Static polymorphism: Function overloading and operator overloading belong to static polymorphism and reuse function names Dynamic polymorphism: Derived classes and virtual functions implement runtime polymorphism
Difference between static polymorphism and dynamic polymorphism:
Static polymorphic function address early binding - The function address is determined at the compilation stage Dynamic polymorphic function address late binding - Determine the function address at run time
class Animal { public: //The Speak function is an imaginary function //The virtual keyword is added in front of the function to become a virtual function, so the compiler cannot determine the function call when compiling. virtual void speak() { cout << "Animals are talking" << endl; } };
If we want to pass in any object, we will call the function of any object
If the function address can be determined at the compilation stage, then static binding
If the function address can only be determined at the running stage, it is dynamic binding
void DoSpeak(Animal & animal) { animal.speak(); }
The following conditions are met:
1. There is an inheritance relationship
2. Subclasses override virtual functions in the parent class
rewrite:
The function return value type is exactly the same as the function name parameter list, which is called rewriting
Polymorphic use:
A parent class pointer or reference points to a child class object
Advantages of polymorphism:
Clear code organization
Strong readability
It is conducive to early and later expansion and maintenance
//Polymorphic implementation //Abstract calculator class //Advantages of polymorphism: the code organization structure is clear and readable, which is conducive to early and later expansion and maintenance class AbstractCalculator { public : virtual int getResult() { return 0; } int m_Num1; int m_Num2; }; //Addition calculator class AddCalculator :public AbstractCalculator { public: int getResult() { return m_Num1 + m_Num2; } }; //Subtraction calculator class SubCalculator :public AbstractCalculator { public: int getResult() { return m_Num1 - m_Num2; } }; //Multiplication calculator class MulCalculator :public AbstractCalculator { public: int getResult() { return m_Num1 * m_Num2; } }; void test02() { //Create addition calculator AbstractCalculator *abc = new AddCalculator; abc->m_Num1 = 10; abc->m_Num2 = 10; cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl; delete abc; //When you run out, remember to destroy it //Create subtraction calculator abc = new SubCalculator; abc->m_Num1 = 10; abc->m_Num2 = 10; cout << abc->m_Num1 << " - " << abc->m_Num2 << " = " << abc->getResult() << endl; delete abc; //Create multiplication calculator abc = new MulCalculator; abc->m_Num1 = 10; abc->m_Num2 = 10; cout << abc->m_Num1 << " * " << abc->m_Num2 << " = " << abc->getResult() << endl; delete abc; } int main() { //test01(); test02(); system("pause"); return 0;
C + + development advocates the use of polymorphism to design program architecture
Because polymorphism has many advantages
Pure virtual functions and abstract classes
In polymorphism, the implementation of virtual functions in the parent class is usually meaningless
It is mainly the content overridden by calling subclasses
Therefore, virtual functions can be changed to pure virtual functions
Pure virtual function syntax:
virtual return value type function name (parameter list) = 0
When there is only one pure virtual function in a class, this class is also called an abstract class
Abstract class features:
Unable to instantiate object Subclasses must override pure virtual functions in abstract classes, otherwise they also belong to abstract classes
base = new Base; // Error, abstract class cannot instantiate object base = new Son;
Virtual destruct and pure virtual destruct
When polymorphism is used, if an attribute in a subclass is opened to the heap, the parent class pointer cannot call the destructor code of the subclass when it is released
Solution:
Change the destructor in the parent class to virtual destructor or pure virtual destructor
Virtual destructor and pure virtual destructor have the following commonalities:
You can solve the problem of releasing subclass objects from parent class pointers
All need to have specific function implementation
Difference between virtual destruct and pure virtual destruct:
If it is a pure virtual destructor, this class belongs to an abstract class and cannot instantiate an object
Virtual destructor syntax:
virtual ~ class name () {}
Pure virtual destructor syntax:
virtual ~ class name () = 0;
Class name:: ~ class name () {} / / global definition
Generally, pointers are used to store such objects
void test01() { Animal *animal = new Cat("Tom"); animal->Speak(); Releasing through the parent class pointer may lead to unclean cleaning of child class objects and memory leakage How? Add a virtual destructor to the base class The virtual destructor is used to solve the problem of releasing subclass objects through the parent class pointer delete animal; }
1. Virtual destruct or pure virtual destruct is used to release subclass objects through parent class pointers
2. If there is no heap data in the subclass, it can not be written as virtual destructor pure virtual destructor
3. Classes with pure virtual destructors are also abstract classes