当前位置:网站首页>Classes and objects (Part 2)
Classes and objects (Part 2)
2022-06-22 01:33:00 【Deer nine pills】
Classes and objects ( Next )
Preface
Hello, everyone , I am a deer Nine pill \color{red}{ Lujiu pill } deer Nine pill , Today we bring you classes and objects ( Next ).
If you have any problems or want to communicate with me in the process of reading my blog or learning, you can add my penguin : 2361038962 \color{red}{2361038962} 2361038962, Or send mail to the corresponding mailbox : 2361038962 @ q q . c o m \color{red}{[email protected]} 2361038962@qq.com, I will try my best to help you answer !
1. Let's talk about constructors
1.1 Constructor body assignment
When you create an object , The compiler calls the constructor , Give each member variable in the object an appropriate initial value .
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
Although after the above constructor call , Object already has an initial value , But you can't call it initialization of class object members , The statement in the constructor body can only call it as an initial value , It can't be called initialization . Because initialization can only be initialized once , The constructor body can be assigned multiple times .
1.2 Initialization list
Initialization list : With a The colon starts , Then there is a Comma separated list of data members , Every " Member variables " Followed by a Initial value or expression in parentheses .
// Function body initialization
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Initialization list
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
// There is still something in the braces
}
// We can even mix it up like this
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
{
_day = day;
}
Conclusion : The initialization list can be considered as the place where the object members are defined .
【 Be careful 】
Each member variable can only appear once in the initialization list ( Initialization can only be done once )( Why can I initialize only once ? Because that's where the definition is !)
Class contains the following members , Must be placed in the initialization list position to initialize :( In addition to the following three types , Other types can be initialized in the initialization list , You can also initialize in the function body )
- Reference member variables
- const Member variables
- Custom type members ( This class has no default constructor )
int iref = 10;
class A
{
public:
A(int a)
:_a(a)
{
}
private:
int _a;
};
class B
{
public:
B(int a)
:_aobj(a)
, _ref(iref)
, _n(10)
{
}
private:
A _aobj; // There is no default constructor
int& _ref; // quote
const int _n; // const
};
ask : For members of custom types that do not have a default constructor , If we do not use the way of initializing the list , What else can we do to initialize it ?
answer :
B(int a)
{
A aa(a);//A Is the type name of the custom type
_aa = aa;//_aa Is the member variable name of the custom type
}
Be careful : The parameters in the initialization list can come from four sources :
Shape parameter .
A(int a) :_a(a)//_a Is a member variable { }Global variables .
A() :_ref(iref)//ref Is a member variable { }Constant values .
A() :_b(10)//_b Is a member variable { }C99 Initialization when declared in .
class A { public: A(int a) { } private: int _a = 10; }; // At this point we do not explicitly write out the initialization list , But the above code should look like the following in the compiler's view class A { public: A(int a) :_a(10) { } private: int _a = 10; };
Be careful 1:
The following is wrong :
class A
{
public:
A(int a)
:_a(a = 10)
{
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A a1;
return 0;
}
In this way, the compiler will report an error , The compiler will prompt that no appropriate default constructor is available , So we make the following changes :
class A
{
public:
A(int a = 20)
:_a(a = 10)
{
_a = a;
cout << a << endl;
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A a1;
return 0;
}
The output is as follows :

analysis : Initializes the assignment expression in the list a = 10 Successfully executed , therefore a It's assigned to 10, Also returns the value a namely 10 take _a Initialize to 10, And then execute _a = a, When this statement is executed, it is equivalent to not executing , Did not affect the final result .
Look at the code below :
class A
{
public:
A(int a = 20)
:_a(a = 10)
{
_a = a;
cout << a << endl;
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A a1(50);
return 0;
}
Output results :

analysis :50 Assigned to a formal parameter a, So it doesn't have any effect on the final result .
Now look at the following code :
class A
{
public:
A(int a = 20)
:_a(a = 10)
{
_a = a;
cout << a << endl;
cout << _a << endl;
}
private:
int _a = 50;
};
int main()
{
A a1;
return 0;
}
Output results :

The output is still 10, At this point, we can draw a conclusion : The priority of the default value initialized in the declaration (_a = 50) Than we explicitly give in the initialization list a The priority is lower . The initialization value given in the declaration is an alternate choice . It is similar to the default value in the function we usually define .
Conclusion :C++11 When defining a class, the default value given to a member variable is used in the initialization list .
Conclusion : The initialization list will go through in any case , Whether or not we explicitly give . Whether or not the constructor we give will form the default constructor , The compiler will call its default constructor to initialize the custom type in the initialization list . For example, the following code :
class Time
{
public:
Time()
{
_hour = 1;
_minute = 1;
cout << _hour << "-" << _minute << endl;
}
private:
int _hour;
int _minute;
};
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
cout << _year << "-" << _month << "-" << _day;
}
private:
int _year;
int _month;
int _day;
Time t1;
};
int main()
{
Date d1(2022, 5, 23);
return 0;
}
Program run results :

analysis : The one above us Date Constructors are not one of the three default constructors , However, the custom type member variable is called for the custom type t1 namely Time Default constructor for class .
Try to initialize with an initialization list , Because whether you use the initialization list or not , For custom type member variables , Be sure to use the initialization list first .
Be careful : We mentioned before , There are three default constructors : Full default constructor 、 Parameter free constructor 、 The constructor generated by the compiler by default when we do not write , No matter which of the above , Will call their constructors for custom types by default , This process is completed in the initialization list , As for built-in types , Because there is no value to initialize , So there are meaningless numbers .
Pay attention to the following situation :
class Date { public: Date(const Date& q)// copy constructor { } private: int _year; int _month; int _day; }; int main() { Date d1; return 0; }The above code program will report an error : No suitable default constructor is available .
Be careful : The copy constructor itself is also a constructor , It's just a special constructor , But once the copy constructor appears , The compiler will no longer generate the default constructor . The copy constructor appears in the above code , So the default constructor is no longer generated automatically , So the compiler will report an error .
The order in which member variables are declared in a class is the order in which they are initialized in the initialization list , It's not about the order in the initialization list
class A { public: A(int a) :_a1(a) , _a2(_a1) { } void Print() { cout << _a1 << " " << _a2 << endl; } private: int _a2; int _a1; }; int main() { A aa(1); aa.Print(); } A. Output 1 1 B. Program crash // Generally, there are wild pointers and so on C. Compile not pass D. Output 1 Random valueRunning results :

So the correct answer should be D, Why? ? Because the initialization order of member variables in the initialization list is only related to the declaration order of member variables in the class , In the example above ,_a2 Declarative , So in the initialization list, the first execution is
\_a2(\_a1)( here _a1 It's a random value , Because there is no initialization ), therefore _a2 It's a random value , And then the execution is\_a1(a), then _a1 Is initialized to 1, So the output is1 Random value.
1.3 explicit keyword
Constructors can not only construct and initialize objects , For a single parameter constructor , It also has the function of type conversion .
class Date
{
public:
Date(int year)
:_year(year)
{
}
private:
int _year;
};
void TestDate()
{
Date d1(2022);
// Assign a value to a date type object with an integer variable
// The actual compiler will use 2022 Construct an anonymous object , Finally, give... A nameless object d2 Object to assign
Date d2 = 2022;
}
Draw pictures to understand :

In the above process, two functions will be called : Constructors + Copy structure ( The following assignment of variables of the same type calls the copy constructor , Because it's creating a new object d2)
Of course , In this place, many compilers will perform an optimization , Can use directly 2022 To construct a Date Type of d2 Variable , Eliminates intermediate type conversions and temporary variables , The constructor will only be called once .
explicit The role of keywords : use explicit Modifier constructor , The implicit conversion of the one parameter constructor will be disabled .. That is, it is impossible to put int Type conversion to Date Type generates temporary variables , If you continue to run the above code, the program will report an error , Because the operation of type conversion cannot be performed .
Look at the code below :
class Date
{
public:
Date(int year)
{
_year = year;
}
private:
int _year;
};
void TestDate()
{
Date d1(2022);
Date& d2 = 2022;
}
int main()
{
TestDate();
return 0;
}
There will be problems after the above code runs , Why? ? Because temporary variables are constant , Cannot be quoted by ordinary references , This is an extension of authority , If you want to reference a temporary variable , You can only use a constant quote to refer to , As the following code demonstrates :
class Date
{
public:
Date(int year)
{
_year = year;
}
private:
int _year;
};
void TestDate()
{
Date d1(2022);
const Date& d2 = 2022;
}
int main()
{
TestDate();
return 0;
}
Be careful : After this temporary variable is referenced, it will not be completely destroyed until it is out of scope !
So what is the use of this grammar ? Look at the code below :
void Func(const std::string& s)
{
}
int main()
{
std::string s1 = "hello";
Func(s1);// This kind of transmission can be undoubted
Func("hello");// With a temporary variable and implicit type conversion, this parameter transfer becomes legal , And it makes it more convenient to transfer parameters
//"hello" A temporary variable is formed after implicit type conversion , Then this temporary variable is constant , The type is const string, So you must use a constant quote to receive
}
2. static member
2.1 Concept
Declare as static Class member of be called Static member of class , use static Embellished Member variables , be called Static member variable ; use static modification Of Member functions , be called Static member functions . Static member variables must be initialized outside the class
Interview questions : Implement a class , Calculate how many class objects are created in the program .
First, let's look at the following interview question , In the following program code , type A How many times has the copy and constructor of been called ?
class A{
};
A Func(A a)
{
A copy(a);
return copy;
}
int main()
{
A a1;
A a2 = Func(a1);
}
We can calculate the number of calls by modifying the following code :
int count = 0;
class A
{
public:
A()
{
count++;
}
A(const A& aa)
{
count++;
}
};
But global variables are not good , Because global variables are generally defined in .h In the document , Often included in other .cpp In file , Therefore, problems often occur in the project , We recommend using static member variables :
class A
{
public:
void Print()
{
cout << _count << endl;// Direct access within the class
}
A()
{
count++;
}
A(const A& aa)
{
count++;
}
private:
static int _count;// Statement
};
int A::_count = 0;// Definition , Static member variables can only be defined outside the class
// If _count yes public The powers of the , There are two access methods outside the class :
Date d1;
d1._count;// Access through the instantiated object of a specific class
A::_count;// Access through classes
ask : What is the difference between a static member variable and a normal member variable ?
answer : Static member variables do not take up space on the stack , Exist in static area , Belong to the whole class , All objects belonging to a class , It doesn't belong to an object , When we use
sizeof()When calculating the size of a class member or class type , Static member variables are not included . for example :class A { public: A() { count++; } A(const A& aa) { count++; } private: static int count; }; int main() { cout << sizeof(A) << endl; }The output is 1.
ask : Whether the static member variables are initialized in the initialization list ?
answer : No , Because only specific objects are initialized in the initialization list .
Except that member variables can be static , Member functions can also be static , The most important feature of member functions is : No, this The pointer .
There are two ways to access static member functions outside the class :
class A
{
public:
static void Func()
{
}
};
int main()
{
A a1;
a1.Func();// Use instantiated members of a class to call static member functions
A::Func();// Use the class name of the class to call the static member function
return 0;
}
No matter which of the above two invocation methods , Just to break through the class domain .
2.2 characteristic
- Static members are shared by all class objects , It doesn't belong to a specific instance
- Static member variables must be defined outside the class , Do not add... When defining static keyword
- Class static members are available class names :: Static members or objects . Static members to access
- Static member functions have no hidden this The pointer , Cannot access any non static members
- Static members are like ordinary members of a class , Also have public、protected、private3 Access levels , You can also have a return value
- Uninitialized static member variables default to 0, But be sure to explicitly define , It can be uninitialized .
【 problem 】
- Can static member functions call non static member functions ?
- Can a non static member function call a static member function of a class ?
3.C++11 Initializing new gameplay for members of .
C++11 Supports initialization and assignment of non static member variables when declared , But note that this is not initialization , Here is the default value for the declared member variable .
Be careful : Static member variables cannot be assigned default values , Can only be defined and initialized outside the class , Why? ? Because this is just a statement , Not really a definition , The initialization list is only used when explicitly creating objects .
The following code is wrong :
class A
{
private:
int _a = 1;
static int _ref = 10;// Here is the wrong , Because static member variables can only be defined and initialized outside the class
};
// The following is true
class A
{
private:
int _a = 1;
static int _ref = 1;// Here is the wrong , Because static member variables can only be defined and initialized outside the class
};
int A::_ref = 10;
4. Friends
Friends are divided into : Friend functions and friend classes
Friends provide a way to break through encapsulation , Sometimes it provides convenience . But friends will increase the degree of coupling , Broke the package , So friends should not use more .
4.1 Friend function
Friend functions can directly access private members of a class , It is an ordinary function defined outside the class , Not of any kind , But you need to declare inside the class , It is necessary to add friend keyword .
Classic use of friend functions :
class Date
{
friend ostream& operator<<(ostream& out, const Date& d);// stay operator<< Functions can be accessed outside the class Date Member variables of class
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out,const Date& d)
{
out << d._year << "-" << d._month << "-" << d._day << endl;
return out;
}
int main()
{
Date d1(2022, 5, 20);
cout << d1;
return 0;
}
explain :
Friend functions can access private and protected members of a class , But not a member function of a class
Friend function cannot be used const modification
Friend functions can be declared anywhere in the class definition , Not restricted by class access qualifiers
A function can be a friend function of multiple classes
Here is an example :
class Date; // ask : Why add a pre declaration here ? // answer : Because in Time In the face Print In the declaration of a friend function , Look forward and you won't find Date Class declaration or definition , So it must be declared here Date Is the name of a class , About specific Date Class definitions can be found later class Time { friend void Print(const Date& d, const Time& t);//Print yes Time Friend function of class , stay Print Function can access Time Member variables of class public: Time(int hour = 0, int minute = 0, int second = 0) { _hour = hour; _minute = minute; _second = second; } private: int _hour; int _minute; int _second; }; class Date { friend void Print(const Date& d, const Time& t);//Print yes Date Friend function of class , stay Print Function can access Date Member variables of class public: Date(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; Time _t; }; void Print(const Date& d,const Time& t) { cout << d._year << "-" << d._month << "-" << d._day << "-"; cout << t._hour << "-" << t._minute << "-" << t._second << endl; } int main() { Date d1(2022, 5, 20); Time t1; Print(d1, t1); return 0; }The calling principle of friend function is the same as that of ordinary function
Be careful : The following friend functions are used incorrectly , And now C++ There is no such syntax to implement :
class Time
{
friend void Date::Print();
public:
Time(int hour = 0, int minute = 0, int second = 0)
{
_hour = hour;
_minute = minute;
_second = second;
}
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << "-";
cout << _t._hour << "-" << _t._minute << "-" << _t._second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
int main()
{
Date d1(2022, 5, 20);
d1.Print();
return 0;
}
If we want to Date Class Time Member variables in class , There is only one way , Will be Date Declare as Time Friends class , There is no other way than eating out , namely C++ It is not supported to declare a member function in a class as a friend function of a class .
4.2 Friend class
All member functions of a friend class can be friend functions of another class , Can access non-public members in another class .
Classic use of friend classes :
class Time
{
friend class Date;//Date yes Time Friends class , Can be in Date In class access Time Member variables of
public:
Time(int hour = 0, int minute = 0, int second = 0)
{
_hour = hour;
_minute = minute;
_second = second;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << "-";
cout << _t._hour << "-" << _t._minute << "-" << _t._second << endl;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
int main()
{
Date d1(2022, 5, 20);
d1.Print();
return 0;
}
Friendship is one-way , Not exchangeable .
For example Time Classes and Date class , stay Time Class Date Class is its friend class , So it can be Date Class Time Private member variable of class , But I want to be in Time Class Date Private member variables in a class do not .
Friendship cannot be transmitted
If B yes A Friends ,C yes B Friends , Can't explain C when A Friends .
class A { friend class B; }; class B { friend class C; }; class C { };At this time in C You can access B Member variables and member functions , But not in C Access to A Member variables and member functions .
5. Inner class
5.1 Concepts and characteristics
Concept : If one class is defined inside another class , This inner class is called inner class . Note that this inner class is a separate class , It does not belong to an external class , You can't call the inner class through the object of the outer class . External classes do not have any superior access to internal classes .
Be careful : The inner class is the friend class of the outer class . Notice the definition of friend classes , The inner class can access the data in the outer class through the object parameters of the outer class All members of . But the outer class is not a friend of the inner class .
characteristic :
The inner class can be defined in the outer class public、protected、private It's all right .
Note that the inner class can directly access... In the outer class static、 Members of the enumeration , Objects of external classes are not required / Class name .
sizeof( External class )= External class , It has nothing to do with inner classes .
When defining variables through internal classes, pay attention to adding external class qualifiers .
class A { public: class B { } } int main() { A::B b1;//B yes A The inner class of , Definition B The type of variable must be in the B The external class qualifier is added to the front of the A return 0; }
6. Exercises
seek 1+2+3+…+n, It is required that multiplication and division shall not be used 、for、while、if、else、switch、case Wait for keywords and conditional statements

class Sum { public: Sum() { _ret+=_i; _i++; } static int GetRet() { return _ret; } private: static int _ret; static int _i; }; int Sum::_i = 1; int Sum::_ret = 0; class Solution { public: int Sum_Solution(int n) { Sum a[n]; return Sum::GetRet(); } };Use inner class :
class Solution { public: int Sum_Solution(int n) { Sum a[n]; return _ret; } class Sum { public: Sum() { _ret += _i; _i++; } }; private: static int _ret; static int _i; }; int Solution::_i = 1; int Solution::_ret = 0;Calculate the conversion from date to days

Code :
#include<iostream> using namespace std; bool IsLeapYear(int year) { if((year % 4 == 0 && year % 100 != 0)|| year % 400 == 0) { return true; } else { return false; } } int main() { int SumMonthDay[13] = { 0,31,59,90,120,151,181,212,243,273,304,334,365};// Before storage n-1 The number of days in a month and int year = 0; int month = 0; int day = 0; int ret = 0; cin >> year >> month >> day; ret = SumMonthDay[month - 1] + day;// front n - 1 The sum of months plus the number of days in the current month if(month > 2 && IsLeapYear(year))// Determine if it's a leap year , If it's a leap year and it's crossed 2 One day is added to the month { ret += 1; } cout << ret; return 0; }Print date

Code :
#include<iostream> using namespace std; bool IsLeapYear(int year) { if((year % 4 == 0 && year % 100 != 0)|| year % 400 == 0) { return true; } else { return false; } } int main() { // It is calculated according to the average year int SumMonthDay[13] = { 0,31,59,90,120,151,181,212,243,273,304,334,365};// Before storage n-1 The number of days in a month and int year = 0; int day = 0; cin >> year >> day; for(int i = 0;i < 13; i++) { if(day <= SumMonthDay[i]) { if(i > 2 && IsLeapYear(year))// Judge whether it exceeds 2 Month and judge whether it is a leap year { day -= 1; // If it is a leap year, it will be reduced by one day to become a normal year and the same algorithm } day -= SumMonthDay[i - 1];// Subtracting the days crossed is the remaining days of the current month printf("%d-%02d-%02d",year, i, day); break; } } return 0; }Add up the number of days

Code :
#include<iostream> using namespace std; int GetMonthDay(int year,int month) { int MonthDay[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31};// Store the corresponding days of each month if(month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))// Judge whether it is 2 Months and are leap years return 29; return MonthDay[month]; } int main() { int num = 0; cin >> num; int year = 0; int month = 0; int day = 0; int x = 0;// Store the number of days to add for(int i = 0; i < num; i++) { cin >> year >> month >> day >> x; day += x; while(day > GetMonthDay(year, month)) { day -= GetMonthDay(year, month); month++; if(month == 13) { month = 1; year++; } } printf("%4d-%02d-%02d\n",year, month, day); } return 0; }
7. Understand encapsulation again
C++ It's an object-oriented program , Object oriented has three major features, namely : encapsulation 、 Inherit 、 polymorphic .
C++ By class , Combine the properties and behavior of an object , Make it more consistent with people's cognition of a thing , Will belong to this object Pack everything together ; Selectively open some of its functions through access qualifiers to interact with other objects , For some implementation details inside the object , External users do not need to know , I see. It doesn't work in some cases , Instead, it increases the difficulty of use or maintenance , Complicate the whole thing .
8. Understand object orientation again
It can be seen that object-oriented is actually simulating the abstract mapping of the real world .

边栏推荐
- 利用SSM框架实现用户登陆
- 3分钟,带你玩转聊天机器人自动化【顶级模板】
- Show you how to distinguish several kinds of parallelism
- Record the use process of webscraper
- 【Redis】事件驱动框架源码分析(单线程)
- SQL操作:WITH表达式及其应用
- 4274. suffix expression
- FLowable运行时事务相关的表和表结构
- Tables and table structures related to the flowable runtime transaction
- English语法_副词 - loud /aloud / loudly
猜你喜欢
![[cyw20189] VII. Detailed explanation of HCI command format](/img/ba/c61d4868e6c5da8460541c62649880.png)
[cyw20189] VII. Detailed explanation of HCI command format

LeetCode 5218. 个位数字为 K 的整数之和(枚举)

MySQL 8.0 新特性梳理汇总

記錄webscraper的使用過程
![[ÑÖÏ Simulation Competition] fading (matrix acceleration, cyclic convolution, Gauss elimination)](/img/4a/9dfcb699e36f67e14c036e3ae26417.png)
[ÑÖÏ Simulation Competition] fading (matrix acceleration, cyclic convolution, Gauss elimination)

单点登录SSO与OAuth2 方案

类和对象(下)

将列表分箱,并通过Pyechart绘制柱状图

IDEA 提示 Duplicated code fragment (15 lines long)

ROS 2 driver is now available for ABB manipulator
随机推荐
LeetCode 5242. 兼具大小写的最好英文字母
isnull() ifnull() nullif()
将列表分箱,并通过Pyechart绘制柱状图
English语法_副词_fairly / rather
【ÑÖÏ模拟赛】花萎(矩阵加速,循环卷积,高斯消元)
Install tensorflow and transformer on Orange Pie orangepi4b
Cancellation meeting and automatic refund processing of message queue
同济、阿里获CVPR最佳学生论文,李飞飞获黄煦涛奖,近6000人线下参会
Brief description of advantages and disadvantages of cloud fortress distributed cluster deployment
MySQL collation
==And equals
单点登录SSO与OAuth2 方案
SQL operation: with expression and its application
MySql DUMP 自动备份数据库 Shell 脚本
Spark RDD case: word frequency statistics
[dailyfresh] course record 2
3分钟,带你玩转聊天机器人自动化【顶级模板】
Virtual variables and formatting characters in debugging
颜值、空间、安全、动力齐升级,新捷途X70S 8.79万元起售上市
[project construction] cmake create release and debug projects
