目录
1. 初始化列表
初始化列表存在于构造函数
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
class Date
{
public:
// 初始化列表是每个成员 定义和初始化 的地方
// 不管你写不写,每个成员都要走初始化列表,成员初始化列表的 执行顺序 和声明顺序一致
//如果不写,内置类型:给随机值,自定义类型:调用它的默认构造函数
Date(int year, int month, int day, int& i)
: _year(year)
, _month(month)
,_a(1)
,_refi(i) //等于int& _refi=i;
{
_day = day; // 赋值
}
private:
int _year; // 每个成员声明
int _month = 1;
int _day = 1;
// C++11支持给缺省值,这个缺省值给初始化列表
// 如果初始化列表没有显示给值,就用这个缺省值
// 如果显示给值了,就不用这个缺省值
//例如:写了_month的初始化列表,则int _month = 1;中的1,就不会给初始化列表。1也不会去赋值。
// 必须定义时初始化
const int _x = 10; //const类型不可改变,不可赋值,只能初始化
int& _refi; //引用定义时必须初始化
A _a; //自定义类型成员(且该类没有默认构造函数时)
};
有些场景还是需要初始化列表和函数体混着用。
Stack(size_t capacity)
:_array((DataType*)malloc(sizeof(DataType) * capacity))
,_size(0)
,_capacity(capacity)
{
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
memset(_array, 0, sizeof(DataType) * _capacity);
}
总结:
- 能用初始化列表就用初始化初始化列。
2. 单参数构造函数的隐式类型转换
- 编译器识别到了单参数,就进行单参数构造函数,然后这个单参数就变成一个类。
- 如果不想发生 单参数构造函数的隐式类型转换 或者 多参数构造函数的隐式类型转换(c++11支持),可以在构造函数的声明和定义前加explicit。
- 一个表达式,连续的步骤里面,连续的构造会被合并,拷贝构造也是构造。
class A
{
public:
A(int a) //explicit A(int i) 则取消 隐式类型转换
:_a(a)
{}
private:
int _a;
};
class B
{
public:
B(int b1, int b2) //explicit B(int b1, int b2) 则取消 隐式类型转换
//explicit B(int b1, int b2)
:_b1(b1)
,_b2(b2)
{}
private:
int _b1;
int _b2;
};
...
int main()
{
A aa1(1);
// 单参数构造函数的隐式类型转换
// 用2调用A构造函数生成一个临时对象,再用这个对象去拷贝构造aa2
//例如:const A& ref1 = 2; 中 ref1 就是一个临时对象
// 编译器会再优化,优化用2直接构造
A aa2 = 2;
SeqList s; //该顺序表中存储类对象
s.PushBack(3);
//等价于
/*A aa3(3);
s.PushBack(aa3);*/
// C++11 支持多参数的隐式类型转换
B bb1(1, 1);
B bb2 = { 2, 2 };
const B& ref2 = { 3,3 };
return 0;
}
3. 匿名对象
- 匿名对象特点:生命周期只在这一行,A(7); 或 A();
- 有名对象 特点:生命周期在当前局部域,A aa1(6);
- 匿名对象具有常性
...
int main()
{
s.PushBack(A(8));
/*A aa1(8);
s.PushBack(aa1);*/
Solution().Sum_Solution(100);
/*Solution sl;
sl.Sum_Solution(10);*/
return 0;
}
- const引用会延长匿名对象声明周期,本质是将匿名变有名
// ref出了作用域,匿名对象就销毁了
const A& ref = A();
A aa2;
4. 类内的static成员
4.1 static成员
- static成员不储存在类对象内。而是存在静态区,所以静态成员变量属于所有对象,属于整个类。
- 由于上述原因,private的static成员的声明不能给缺省值。初始化类表里也不会有static成员。静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。定义eg: int A::n=0;
4.2 static成员函数
- 静态成员函数没有隐藏的this指针,不用类对象就可调用
- static成员函数不可访问非 static成员。非static成员函数 可访问 static成员。
- 也可像static成员一样使用A::,而不通过对象调用
牛客题目:关于static的题目
5. 友元
5.1 友元函数
- 友元函数可访问类的私有和保护成员,但不是类的成员函数
- 友元函数不能用const修饰
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
- 一个函数可以是多个类的友元函数
- 友元函数的调用与普通函数的调用原理相同
5.2 友元类
- 友元类可访问类的私有和保护成员
- 友元关系是单向的,不具有交换性。
- 友元关系不能传递
如果B是A的友元,C是B的友元,则不能说明C时A的友元。
友员类的例子如下:
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量。。。。。。。。
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 = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接访问时间类私有的成员变量
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
}
6. 内部类
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。
- B类只受A类域和访问限定符的限制,但其实他们是两个独立的类
- 内部类就是外部类的友元类,可访问外部类的私有和保护成员。
- 外部类不可访问内部类的私有和保护成员。