1.再探构造函数
1.在类和对象上中实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数还有一种方法就是初始化列表。初始化列表的使用方式是以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每一个成员变量后面跟一个放在括号中的初始值或表达式。
2.每一个成员变量在初始化列表中只能出现一次。
3.引用成员变量,const成员变量,没有默认构造的类类型变量,必须放在初始化列表位置进行初始化,否则会编译报错。
4.C++11支持在成员变量声明的位置给缺省值,这个缺省主要是给没有显示初始化列表的初始化成员使用的。
5.尽量使用初始化列表。
6.初始化列表按照成员变量在类中声明顺序进行初始化。建议声明顺序和初始化顺序保持一致
以下为简单的初始化列表的案例:
#include<iostream>
using namespace std;
class Time
{
public:
Time(int hour)
:_hour(hour)
{
cout << "Time()" <<endl;
}
private:
int_hour;
};
2.类型转换
1.C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。
2.构造函数前面加explicit就不再支持隐式类型转换。
3.static成员
1.用static修饰的成员变量,称为静态成员变量,静态成员变量一定要在类外进行初始化。
2.静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
3.静态成员变量函数没有this指针。
4.静态成员变量可以访问其他的静态成员,但不能访问非静态成员(静态成员没有this指针).
5.非静态的成员函数可以访问任意的静态成员变量和静态成员。
6.突破类域就可以访问静态成员,有两种方法可以突破类域,第一可以通过类名::静态成员
第二可以 对象.静态成员
7.静态成员也是类的成员,受public,protected,private访问符的限制。
8.静态成员变量不能在声明位置给缺省值初始化。
4.友元
1.友元提供了一种突破类访问限定符封装的方式,友元分为:友元函数和友元类,在函数声明或者类声明前面加friend,并且把友元声明放到一个类的里面。
2.外部友元函数可访问类的私有和保护成员,注意友元函数只是一种声明并不是类的成员函数。
3.友元函数可以在类定义的任何地方声明。
4.一个函数可以是多个类的友元函数。
5.友元类的成员函数都可以是另一个类的友元函数。
6.友元类的关系是单向的,不具有交换性。
7.友元会增加耦合度,破坏了封装,所以友元不宜多用。
#include<iostream>
using namespace std;
//前置声明,否则A的友元函数声明编译器不认识B
class B;
class A
{
//友元声明
friend void func(const A&aa, const B&bb)
private :
int _ a1 = 1;
int_ a2 = 2;
};
class B
{
//友元声明
friend void func(const A&aa,const B&bb);
private:
int_b1 = 3;int_b2 = 4;
};
void func(const A&& aa,const B&bb)
{
cout <<aa._a1<< endl;
cout <<bb>_b1<<endl;
}
int main()
{
A aa;
B bb;
return 0;
}
5.内部类
1.如果一个类定义在另一个类的内部,这个类就叫做内部类。
内部类是一个独立的类,除了受外部类类域限制和访问限定符限制外跟定义在全局的类无异。
2.内部类默认是外部类的友元类。
3.内部类本质也是一种封装,当A类与B类紧密相关的时候,可以考虑把A类设计为B的内部类,当在private或protected的位置时,A类就是B类的专属内部类。
#include<iostream>
using namespace std;
class A
{
private:
static int_k;
int _h = 1;
public:
class B
{
public:
void foo(const A& a)
{
cout << _k <<endl;
cout <<a._h <<endl;
}
};
6.匿名对象
1.用实参定义出来的 对象叫做匿名对象,而用类型对象名定义出来的叫做有名对象。
2.匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可。
7.对象拷贝时的编译器优化
1.现代编译器会为了尽可能提高程序的效率,在不影响正确性的情况下省略拷贝从而达到目的。
2.根据编译器的不同从而优化的程度也不同,即省略拷贝的效果也不同。