
◆博主名称:少司府
欢迎来到少司府的博客☆*: .。. o(≧▽≦)o .。.:*☆
⭐数据结构系列个人专栏:
⭐C++基础个人专栏:
⭐名不显时心不朽,再挑灯火看文章
目录
[三、static 成员](#三、static 成员)
[3.1 定义及性质](#3.1 定义及性质)
[3.2 static 成员的运用](#3.2 static 成员的运用)
[4.1 友元函数](#4.1 友元函数)
[4.2 友元类](#4.2 友元类)
[6.1 匿名对象定义](#6.1 匿名对象定义)
[6.2 匿名对象例子](#6.2 匿名对象例子)
一、类型转换
1)、C++⽀持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。
cpp
A aa=1;
// 隐式类型转换,先用1构造一个临时对象,再拷贝构造给aa
此处编译器会优化:面对连续的构造和拷贝构造,编译器会合二为一
其意义如下:
cpp
A aa1={2,2}; // A有两个参数,C++11支持该写法
st.Push(aa1);
//可以直接写为
st.Push({2,2});
2)、构造函数 前⾯加explicit就不再⽀持隐式类型转换。
cpp
explicit A()
{
//...
}
3)、类类型的对象之间也可以隐式转换,需要相应的构造函数⽀持
cpp
B b = aa3;
const B& rb = aa3; // 引用指向aa3构造出的临时对象
二、再探构造函数
1)、构造函数完成初始化还可以使用初始化列表,以冒号开始,以逗号分割成员变量,括号后跟初始值或表达式
2)、每个成员变量在初始化列表内只能出现一次,语法上可以理解为在列表中定义(并初始化)每个成员变量
3)、const 成员、引用成员以及没有默认构造的自定义成员必须用初始化列表完成初始化
cpp
class Date
{public:
Date(int year,int month,int day)
:_year(year)
,_month(month)
,_day(day)
,_n(1)
,_ra(2)
,_t(3)
private:
int _year=2026,_month=4,_day=12; // C++11的补丁,给出缺省值,只是声明不是定义,没有开空间
const int _n; // 不是缺省构造函数、没有传参的时候
int& ra; // 若没有完成初始化,就会用这里的缺省值
Time _t;
}
4)、除了静态成员外,每个成员都要先走初始化列表
5)、初始化列表中成员变量按声明顺序进行初始化

三、static 成员
3.1 定义及性质
1)、用static修饰的成员变量叫做++静态成员变量++,需要在类外初始化
2)、静态成员被该类的所有成员共享,不属于某个具体对象,不存储在对象中,在静态区
3)、静态成员函数没有this指针,只能访问静态成员
cpp
class A
{public:
static void GetCount()
{
_a++;
cout << _a << endl;
}
private:
static int _a;
};
int A::_a=1;
3.2 static 成员的运用

题目描述如图:求1加到n的和,不能用公式(乘除法)、循环、条件判断语句,这里,我们可以用类和对象的知识解题。

如图,传入n,我们构造n个对象,每构造一次 _i++ 记录是第几次构造,_ret+=_i 加上之前的结果,返回递加之和。
四、友元
4.1 友元函数
1)、友元提供了⼀种突破类访问限定符封装 的⽅式,友元分为:++友元函数++ 和++友元类++,在函数声明或者类 声明的前⾯加friend,并且把友元声明放到⼀个类的⾥⾯。
2)、外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数
3)、友元函数可以在类定义的任何地⽅声明,不受类访问限定符限制。
4)、⼀个函数可以是多个类的友元函数。
cpp
class B; // 前置声明,告诉编译器有个类叫B
class A{
friend void Func(const A& aa,const B& bb);
private:
int _a1=1;
int _a2=2;
};
class B{
//...
};
void Func(const A& aa,const B& bb)
{
cout << aa._a1 << ' ' << bb._b1 << endl;
}
4.2 友元类
1)、友元类中的成员函数 都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员。
cpp
class A{
friend class B; // 友元类,B中可访问A中所有成员,B是A的友元类
private: // friend class 是友元类名,放在被访问类的内部
int _a1=1;
};
2)、有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多⽤。
· 友元类的关系是单向的,不具有交换性,⽐如A类是B类的友元,但是B类不是A类的友元。
· 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
五、内部类
1)、如果**⼀个类定义在另⼀个类的内部** ,这个类就叫做内部类。内部类是⼀个独⽴的类,跟定义在全局相⽐,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
2)、内部类默认是外部类的友元类。
cpp
class A
{
private:
static int _k;
int _h = 1;
public:
class B // B默认就是A的友元
{
public:
void foo(const A& a)
{
cout << _k << endl; //OK
cout << a._h << endl; //OK
}
int _b1;
};
};
int A::_k = 1;
内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么可以考 虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其 他地⽅都⽤不了。
六、匿名对象
6.1 匿名对象定义
1)、⽤类型(实参)定义出来的对象叫做匿名对象,相⽐之前我们定义的类型对象名(实参)定义出来的叫有名对象。
2)、匿名对象⽣命周期只在当前⼀⾏,⼀般临时定义⼀个对象当前⽤⼀下即可,就可以定义匿名对象。
6.2 匿名对象例子
cpp
class A{
//...
};
int main()
{
A();// 匿名对象,生命周期只在当前这一行
A(1);
return 0;
}
七、对象拷贝时编译器的优化
1)、现代编译器会为了尽可能提高程序,在不影响正确性的情况下,会尽可能减少一些传参和传返回值过程中可以省略的拷贝
cpp
A aa1=1; // 构造+拷贝构造,编译器优化,只有构造
const A& aa2=1; // 构造,引用指向构造出的临时对象
2)、如何优化C++标准并没有严格规定,取决于各个编译器的实现
cpp
A f2()
{
A aa; //构造
return aa; //传值返回生成临时对象,拷贝构造给生成的临时对象
}
int main()
{
f2().Print(); // 构造+拷贝构造
return 0;
}
本期的分享就到这里,如果觉得博主的文章比较对胃口的话,可以点一个小小的关注~
您的三连是我持续更新的动力~