C + + will provide a default constructor, destructor and default copy constructor
Shorthand method of constructor
CCylinder(double r,double h) { radius=r; height=h; }; ==>CCylinder(double r,double h):radius(r),height(h){}
[this method is limited to constructors]
Allocate space during construction and release space during decomposition
class student { char *name,*stuCode; public: stdent(char *_name,char *_stuCode) { name=new char[strlen(_name)+1]; stuCode=new char[strlen(_stuCode)+1]; strcpy(name,_name); strcpy(stuCode,_stuCode); } void print(){cout<<name<<" "<<stuCode<<endl;} ~student() { delete []name; delete []stuCode; } }; //The memory space allocated during object construction needs to be released during destruction
Object array (array of objects when members)
class CCylinder { ...... }; int main() { CCylinder c[3]; //Fixed size array CCCylinder *cc=new new Cylinder[3]; //Dynamic array ...... delete [] cc; return 1; }
ps: the constructor will be called automatically when creating a fixed size array, but not when creating a dynamic array (remember to release)
give an example:
int main() { int n; cin>>n; CAT *op; op=new CAT[n]; for(int i=0;i<n;i++) { string name; int weight; cin>>name>>weight; op[i].get(name,weight); } sort(op,op+n,cmp); for(int i=0;i<n;i++) { op[i].print(); } delete []op; return 0; }
Secondary pointer
int main() { Cylinder **c=new Cylinder*[3]; for(int i=0;i<3;i++) { cin>>radius>>height; c[i]=new Cylinder(radius,height); } ...... for(int i=0;i<3;i++) delete c[i]; delete []c; return 1; }
copy constructor
Cylinder(Cylinder &r_c);
(its function name is the same as the constructor, but it has only one parameter, that is, the reference of an object of the same kind)
Call copy constructor
Cylinder cylinder2(cylinder1);
Shallow copy (default copy constructor)
Simply copy each data member of the object as an argument to the corresponding data member of the newly declared object.
The default copy constructor provided by the system is to use shallow copy
[when the data member is a pointer, the shallow copy cannot be used, and the constructor must be rewritten
Reason: the address is transmitted, and both will change at the same time]
Deep copy (override copy constructor)
CPerson::CPerson(CPerson &r_p) { name=new char[strlen(r_p. name)+1]; address=new char[strlen(r_p.address)+1]; strcpy(name,r_p.name); strcpy(address,r_p.address); }
[focus on applying for necessary memory]
When is the copy constructor called?
- When an existing object is initialized to create a new object
CPerson person2(person1);
2. When the parameter of a function is an object of a class
void printPerson(CPerson person)
- When you pass the argument object to the formal parameter during the call, you need to create a copy of the argument, and the system will call the copy constructor to implement it.
3. When the return value of a function is an object of a class
CPerson f() { CPerson p("zhang","guangzhou"); return p; } //The system will create a copy of p and return it to the calling function.
BUT: if a reference is used as a function parameter or a function return reference, the copy constructor will not be called
void print() const;
Direct return reference is dangerous and can be defined as const
Assignment of objects
- Assignment form of object:
Object name 1 = object name 2;
Cylinder cylinder1,cylinder2; ....... cylinder2=cylinder1; //Assign the value of each member of cylinder1 to cylinder2
Static member
- If the keyword static is added before a class member, the member becomes a static member.
- Static members belong to the entire class, not to specific objects of the class.
- Static members, including static data members and static function members.
Static data member
class CCylinder { public: double volume(); private: double radius; static double height; //Define height as a static member }; CCylinder cylinder1,cylinder2;
Static member initialization data
[for static data members defined in the class, even if no object is defined, the system will allocate space for them during compilation, and the space will not be released until the end of the program]
- Static data members can only be initialized outside the class. If they are not initialized, the system will assign a value of 0.
Data type class name:: static data member name = value;
double CCylinder::height=10;
- When referencing public static data members outside the class, you can use either the class name or the object name.
Class name:: static data member name
- Static data members solve the problem of data sharing between similar objects
Static member function
- Member functions declared with the keyword static are static member functions.
- Static member functions cannot access non static data members. They can only access static data members and call other static member functions.
- Static member functions are used to handle static data members
- When calling a static member function, the available class name is called in the following format:
Class name: static member function name (parameter table);
- You can also call static member functions through object names
Object name Static member function name (parameter table);
- A static member function belongs to a class. Any object in the class can call it with the object name.
code
#include<iostream> #include<cstdio> using namespace std; const double PI=3.14; class CCylinder { public: CCylinder(double r):radius(r){}; double static getHeight() {return height;}; void static setHeight(double h) {height=h;}; double volume(); private: double radius; static double height; //Define height as a static member }; double CCylinder::volume() { return PI*radius*radius*height; } double CCylinder::height=10; //Initialize the static data member height outside the class int main() { cout<<CCylinder::getHeight()<<endl; CCylinder::setHeight(20); cout<<CCylinder::getHeight()<<endl; CCylinder c1(2),c2(3); cout<<c1.getHeight()<<endl; cout<<c2.getHeight()<<endl; c1.setHeight(30); cout<<c1.getHeight()<<endl; cout<<c2.getHeight()<<endl; return 1; }
Common occasions for static data members
- Number of objects used to save flow changes
- As a flag, it indicates whether a specific action occurs
- A pointer to the first or last member of the linked list
Friends
- In order for functions outside the class or another class to access private members in the class, they can be declared as friends.
- The declaration of friend can only appear inside the class definition and is declared with the keyword friend.
- Friends can be friend functions or friend classes.
[if an ordinary function outside a class or a member function of another class is declared as friend in a class, it is called a friend function of this class.]
contrast
Normal functions access objects as arguments
class Time { public: Time(int h=12,int m=12,int s=12):hour(h),minute(m),second(s){} int getHour(){return hour;} int getMinute(){return minute;} int getSecond(){return second;} private: int hour,minute,second; }; void display(Time& t) //when display() is a normal function { cout<<t.getHour()<<":"<<t.getMinute()<<":"<<t.getSecond()<<endl; } void main( ) { Time t1(10,13,56); display(t1); //Call the display function, and the argument t1 is a Time class object }
When an ordinary function is declared as a friend function
class Time { public: Time(int h=12,int m=12,int s=12):hour(h),minute(m),second(s){} int getHour(){return hour;} int getMinute(){return minute;} int getSecond(){return second;} friend void display(Time &t); //declare as friend private: int hour,minute,second; }; void display(Time& t) //when normal function turns into friend { t.hour=25; t.minute=62; //dangerous cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl; } void main( ) { Time t1(10,13,56); display(t1); //Call the display function, and the argument t1 is a Time class object }
Declare a member function of another class as a friend
code
#include<iostream> using namespace std; class Date; //Advance reference declaration for Date class class Time { int hour,minute,second; public: Time(int h,int m,int s); void display(Date &d); //display is a member function, and the formal parameter is a reference to the Date class object }; class Date { int year,month,day; public: Date(int y,int m,int d); friend void Time::display(Date &d); //Declare the display function in Time as a friend member function }; Time::Time(int h,int m,int s):hour(h),minute(m),second(s){} void Time::display(Date &d) { cout<<d.year<<"/"<<d.month<<"/"<<d.day<<" "<<hour<<":"<<minute<<":"<<second<<endl; } Date::Date(int y,int m,int d):year(y),month(m),day(d){} int main() { Date date(2020,4,26); Time t(28,18,18); t.display(date); return 1; }
Friend class
[if you need to declare all member functions in one class (class B) as friend functions of another class (Class A), you can directly declare class B as friends of class A.]
code
#include<iostream> using namespace std; class Date; class Time { int hour,minute,second; public: Time(int h,int m,int s):hour(h),minute(m),second(s){} friend class Date; }; class Date { int year,month,day; Time t; public: Date(int y,int m,int d,Time t1):year(y),month(m),day(d),t(t1){} void print() { cout<<year<<"/"<<month<<"/"<<day<<" " <<t.hour<<":"<<t.minute<<":"<<t.second<<endl; } };
Example: comparing member functions with friend functions
include<iostream> using namespace std; class A { double a; public: A():a(0){} A(double a1):a(a1){} double add(A &r_a) { return a+r_a.a; } double minus(A &r_a) { return a-r_a.a; } ~A(){} friend double add(A &r_a1,A &r_a2); friend double minus(A &r_a1,A &r_a2); }; double add(A &r_a1,A &r_a2) { return r_a1.a+r_a2.a; } double minus(A &r_a1,A &r_a2) { return r_a1.a-r_a2.a; } int main() { A a1(2),a2(3); cout<<a1.add(a2)<<endl; cout<<a1.minus(a2)<<endl; cout<<add(a1,a2)<<endl; cout<<minus(a1,a2)<<endl; return 1; }
Example: friend class
#include<iostream> using namespace std; class A { double a; public: A():a(0){} A(double a1):a(a1){} double add(A &r_a) { return a+r_a.a; } double minus(A &r_a) { return a-r_a.a; } ~A(){} friend class B; }; class B {public: double add(A &r_a1,A &r_a2) { return r_a1.a+r_a2.a; } double minus(A &r_a1,A &r_a2) { return r_a1.a-r_a2.a; } }; int main() { A a1(2),a2(3); cout<<a1.add(a2)<<endl; cout<<a1.minus(a2)<<endl; B b; cout<<b.add(a1,a2)<<endl; cout<<b.minus(a1,a2)<<endl; return 1;}
this pointer
Implicit use:
- Each object maintains a pointer to itself, which is called the this pointer.
- Each object can determine its own address by using the this pointer.
this pointer is an implicit parameter when referring to a member inside an object.
double Cylinder::volume() { return PI*radius*radius*height; }
Can be written as:
double Cylinder::volume(Cylinder *this) { return PI*(this->radius)*(this->radius)*(this->height); }
[this pointer is used implicitly. It is passed to the member function as a parameter. This process is automatically implemented by the compilation system.]
Display usage:
- When the parameter name of the method is the same as the name of the member variable, you need to explicitly use the this pointer to distinguish it
private: double radius; double height; Cylinder::Cylinder(double radius, double height) { this->radius=radius; this->height=height; }
[static member function does not belong to an object, so this pointer cannot be used in static member function, nor can it access non static members in class]
give an example:
class CCylinder { public: CCylinder():radius(1),height(1){} CCylinder(double r,double h):radius(r),height(h){} double volume(){ return 3.14*radius*height; } CCylinder compare(CCylinder &c) { //Returns the larger of the two objects if(volume()>c.volume()) return *this; else return c; } void print(){ cout<<"radius:"<<radius<<" ,height"<<height<<endl; } private: double radius; double height; };
Compound class
- Composite class refers to a class that takes the object of other classes (not the object of composite class itself) as the parameter of its data member or member function.
class CHost{ . ... } class CPeripheral{ ... } class CComputer{ private : CHost host; //Object member CPeripheral peripheral; //Object member ... }
Initialization of object members of a composite class
① initialize the object member first (call the constructor of this class)
② initialize other non object members in the class;
give an example:
#include <iostream> using namespace std; class Point { float x; float y; public: Point(); Point(float _x,float _y); void print(); }; Point::Point(){ } Point::Point(float _x,float _y) { x = _x; y = _y; } void Point::print() { cout<<"("<<x<<","<<y<<")"<<endl; } class Circle { float radius; Point center; public: Circle(); Circle(Point p,float r); void setCircle(float r,Point p); void print(); }; Circle::Circle(){} Circle::Circle(Point p,float r):center(p),radius(r) { }//The variable name is center void Circle::setCircle(float r,Point p) { radius = r; center = p; } void Circle::print() { cout<<"radius:"<<radius<<endl; center.print(); } int main() { Point p(5,7); p.print(); Circle c(p,1); // Circle c; c.setCircle(1, p); c.print(); return 0; }
Constant object, constant member function and constant data member
Constant object
- Objects declared with the keyword const are called constant objects (object constants)
Class name const Object name Cylinder const c1(1,2);
- When declaring a constant object, it must be initialized at the same time, and the data members in the object cannot be reassigned elsewhere in the program.
- If an object is declared as a constant object, the non const member functions of the object cannot be called to avoid that these functions will modify the value of the data member in the object.
Constant member function
- The member function decorated with the keyword const is a constant member function.
Type function name (parameter table) const double getAB() const; void print() const;
Constant data member
- Data members declared with the keyword const are called constant data members.
- The value of a constant data member cannot be changed.
- Constant data members can only be initialized through the constructor's parameter initialization list
const int hour; Time::Time(int h) {hour=h;} //error Time::Time(int h):hour(h){} //ok