𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary_walk
⸝⋆ ━━━┓
- 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━ ➴ ⷯ本人座右铭 : 欲达高峰,必忍其痛;欲戴王冠,必承其重。
👑💎💎👑💎💎👑
💎💎💎自💎💎💎
💎💎💎信💎💎💎
👑💎💎 💎💎👑 希望在看完我的此篇博客后可以对你有帮助哟👑👑💎💎💎👑👑 此外,希望各位大佬们在看完后,可以互相支持,蟹蟹!
👑👑👑💎👑👑👑
WeChat_20240806081335
目录:
一:构造函数的补充
二:static修饰的变量以及函数
三:友元
四:内部类
五:匿名对象
六:拷贝对象的一些优化
七:深度理解封装
思维导图:
1:构造函数的补充
1.1初始化列表
当类的成员里面有const 修饰的时候,我们在定义构造函数的时候,若不对当前const 修饰的
变量进行初始化,是有问题的。
const 修饰的变量必须在进行声明的时候就进行初始化。
C++针对此问题引入了初始化列表:初始化列表是类的每一个成员进行定义的地方,并且只
调用初始化例表一次
对于自定义类型的成员,引用类型的成员并且对应的类没有默认构造函数的,也需要借助
初始化列表来进行完成
对于引用和自定义类型成员进行初始化:
类的成员声明和定义
1.2 注意:
1:每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)ex
2: 类中包含一些特殊的成员(3种情况),必须放在初始化列表位置进行初始化
3:不管是否显示在初始化列表中对类的成员进行初始化,编译器都会默认在初始化列表中对所有
是类的成员进行初始化
4:初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面
跟一个放在括号中的初始值或表达式。
5:当定义的对象给出了初始化的值,在调用初始化列表的时候就会以给出的参数进行初始化,若
是没有给出参数,就看看是否有缺省值,有的话使用缺省值,若是2个都没有编译器就会使用随机
值
栗子见下:
6:关于在初始化列表里面对类的成员进行初始化的先后顺序问题:是以类的成员定义的先后顺序
进行初始化的
栗子见下:
关于初始化列表具体使用场景:与函数体混着用
所以建议:最后自己写初始胡列表,自己不写,编译器也会默认调用初始化列表,来进行成员的定义
1.3 explicit关键字
对于自定义类型与内内置类型之间的转换的理解:
当我们不想让自定义类型与内置类型之间进行转换 的时候可以使用对初始化列表使用关键字
explicit
类型转换涉及的权限问题:
2:static修饰的变量以及函数
2.1概念
类的成员在声明的时候使用关键字static进行修饰,称之为类的静态成员
static修饰的函数称之为静态成员函数
注意对静态成员变量一定要在类的外面进行初始化(定义)
2.2应用
当类里面涉及到静态成员的时候,出于惯性思维,会在初始化列表里面对静态成员进行定义;但是
此时编译不过:
这是因为:静态成员变量并不是属于某一个指定对象所拥有的,而是属于所有对象使用的;对这
个问题的理解就像是成员函数的存放一样。
康康下面这个例子,就可以知道了
对静态成员定义:类外 + 变量名字前指明类域 + 没有static 修饰
类外如何使用访问静态成员???
类外访问静态成员有3种方式:
第一种:指明静态成员所在的类域(默认是全局找的)
第二种:借助对象访问
第三种:借助指针访问
静态成员受到访问限定符限制:
静态成员函数:
2.3 static 的特性
1.静态成员为所有的类对象共享,不属于某一个对象,是放在静态区的
2.静态成员变量必须在类外进行定义并指明类域,定义时不能加关键字 static
3. 类的静态成员的访问:类名 :: 静态成员变量名字 或者对象.静态成员变量或者指针
4.静态成员函数是没有隐藏的this指针
5.静态成员也是类的成员,也受到访问限定符的限制
6. 静态成员函数可以调用静态成员变量
7.静态成员函数可以调用静态成员函数(并不需要this指针的使用)
8.非静态成员函数可以调用静态成员函数;也可以访问静态的成员变量(不需要 this指针)
9. 静态成员函数不能调用非静态成员函数也不能访问非静态成员变量(静态成员函数是没有
this 指针的)
本质:静态成员函数是没有this是指针的;对非静态的成员函数和非静态的成员变量都是借
助this指针来进行访问的
小试牛刀一把:涉及到析构函数的调用以及被static 修饰的类
已知:类A,B,C,D 已经存在,下面析构函数调用的先后顺序是?
答案:A,B ,D ,C
1)new 和 delete 匹配使用:delete pa:直接调用的析构函数
2)一般默认在对象生命周期结束的时候,编译器自动调用析构函数
3)先创建的对象后进行析构函数的调用
4)D 虽然被static 进行修饰了,但是受到 main()这个函数栈帧的作用域的限制,所以D 比C 调用
析构函数的要早
3:友元
3.1概念
友元其实是打破了对类的封装:当我们对类的成员属性设置为private或者protected的时候,在类
是不能直接进行访问的,这个时候借助友元函数或者友元类进行访问就
3.2友元类
以Time 这个类作为例子吧:有时我们在一个类的外面是无法直接访问另一个类的私有成员的,此
时可以借助友元类;声明Date 是Time 这个类的友元类;注意Time 类是不能访问Date 类的私有成
员 的。
友元类是单向的,不能双向互相访问
Date 是 Time 这个类的友元类:就好比,A 是B 的朋友,站在A 的角度上理解就是:
A 可以随意的出入B 的家里,进行对B 的访问,但是此时 B 不一定把A 视为朋友,所以B 不能访问
到A 的成员
代码:
class Time
{
private:
int _hour;
int _min;
int _sec;
public:
friend class Date;//声明日期为时间的友元类(也就是Date里面可以访问Timel里面的私有成员)
Time(int hour = 0,int min = 0,int sec = 0)
:_hour(hour)
,_min(min)
,_sec(sec)
{}
};
class Date
{
public:
void Print()
{
cout << _year << '/' << _month << '/' << _day << endl;
cout << _t._hour << ':' << _t._min<< ':' << _t._sec << endl;
}
Date(int year = 2024, int month = 4, int day = 2)//初始化列表
:_year(year)
, _month(month)
, _day(day)
{
cout << "Date()" << endl;
}
void SetTimeOfDate(int hour, int min, int sec)
{
_t._hour = hour;
_t._min = min;
_t._sec = sec;
}
private:
int _year;
int _month;
int _day;
Time _t;//自定义类型
};
int main()
{
Date d(2024, 4, 3);
d.SetTimeOfDate(21, 31, 42);
d.Print();
return 0;
}
运行结果:
3.3友元函数
lass Date
{
public:
//friend ostream& operator << (ostream& _cout, Date& d);//err
friend ostream& operator<< (ostream& _cout,const Date& d);
friend istream& operator>> (istream& _cin, Date& d);
Date(int year, int month, int day)//初始化列表
:_year(year)
, _month(month)
,_day(day)
{}
void Print()
{
cout << _year << '/' << _month << '/' << _day << endl;
}
/*ostream& operator << (ostream& _cout)
{
_cout << _year << '/' << _month << '/' << _day << endl;
return _cout;
}*/
private:
int _year;
int _month;
int _day;
};
ostream& operator<< (ostream& _cout,const Date& d)
{
_cout << d._year << '/' << d._month << '/' << d._day << endl;
return _cout;
}
istream& operator>> (istream& _cin, Date& d)//注意第二个参数不能用const 修饰
{
//一开始是不能对类外私有成员进行访问的,可以借助友元函数进行操作
_cin >> d._year >>d._month>>d._day;
return _cin;
}
int main()
{
Date d1(2024, 4, 2);
//cout << d1 << endl;//err 此时this 指针和_cout这个参数都进行抢占第一个参数的位置
cin >> d1;
cout << d1 << endl;
return 0;
}
注意:
1.友元函数不是类的成员,不属于任何类
2.友元函数不属于该类的成员函数,它是定义在类外的普通函数,只是类中声明该函数可以
直接访问类中的private或者protected成员
3.友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看
在类中是否有声明。
4.友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,
同样要看类中是否有声明。
下面小试牛刀一把吧:
选D,你做对了吗?
首先友元函数是不属于类的,不需要对象调用,也就不需要传递this指针;对于选项C 不严谨:只
有非静态的成员函数,才使用对象调用,传递this 指针。
4:内部类
内部类的特点:
1. 内部类可以定义在外部类的public、protected、private都是可以的。
2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象 或者是 类名。
3. sizeof(外部类) = 外部类,和内部类没有任何关系。
4. 内部类在空间上是与外部类相互独立的但是受到外部类的类域的限制
5:匿名对象
书写形式:类名 ()
6:拷贝对象的一些优化
栗子见下:
以下都是在VS 这个编译器上面,不同的编译器可能进行优化不一样。
对于VS 而言:当在一个步骤里面,连续的调用构造函数或连续的调用拷贝构造函数或者是连续的
构造和拷贝构造,编译器会进行优化,直接一步到位,减少函数调用,提升效率。
还是以上面的例子来进行研究:
可能有点同学就会疑惑,为啥下面这个多出一个构造函数的调用,不应该和上面的输出一样吗?
分析:
综合的应用:
7:深度理解封装
结语:
以上就是今日的share,此篇博客主要是对前期类和对象的一些补充和总结啥的。
对于类和对象相关知识还是有点晕晕的友友们,可以自行查看链接:
类和对象的上篇
对于类和对象下的理解还是比较好容易的(当然是建立在前期:对类和对象上,中期的理解),希
望各位老铁们可以有所收获!