初始化列表
在类和对象中,我们介绍过一种成员变量初始化的方法,那就是函数体内初始化。这种初始化依赖于函数体的缺省值和实参,并且无法初始化部分数据,如被const修饰的数据。构造函数体内也无法初始化引用成员变量。
因此,我们在此介绍另一种成员变量初始化的方式:初始化列表。初始化列表的格式为在构造函数后面以‘:’开始,‘,’分隔,并且在成员变量后面的括号里放初始值或者表达式。这样,就完成了初始化列表。需要注意的是,初始化列表中的每个成员变量只需要初始化一次,多次初始化会到导致报错!
诶,有细心的读者就会看到,我下面并没有给_day进行初始化,这会不会报错呢?其实,这并不会报错,因为我在成员变量声明的时候给了个缺省值,当我们没有在初始化列表中初始化某个成员变量的时候,编译器会自动把成员变量中的缺省值作为初始值。但是,其实空间并不是在此时开辟的!根据我们之前学到的函数栈帧的创建我们知道,关于函数内对象空间的创建,在进入函数的时候就已经创建好了,类对象也是一样。
我们应当尽量使用初始化列表初始化我们的成员变量,这样可以尽量保证覆盖到所有类型的数据。所有成员变量都会走初始化列表,如果我们在初始化列表没有写部分成员变量,这些成员变量会去找缺省值,如果没有找到缺省值,则就会被编译器瞎给数据,有的时候给的是0,有德时候给的是随机数。对于没有显示写初始化列表的自定义类型成员就会调用该类的初始化列表。如果还是没有,就会报错了。
在我们写初始化列表的时候,应当按照成员变量的声明顺序写初始化,因为编译器在初始化列表的时候并不是按你初始化列表的顺序从上到下的进行初始化。如下图,并不是先初始化_month再初始化_year,而是按照顺序,_year->_month->_day。
class Date
{
public:
Date(int year, int month, int day)
:_month(month)
,_year(year)
{}
private:
int _year;
int _month;
int _day = 2;
};
隐式类型转换
C++支持隐式类型转换,也就是不需要明显的先构造一个类对象出来,在进行赋值初始化。但是需要对应的构造函数来进行支持。如A的构造函数只有一个int 类型的形参x,那么想要定义一个类只需要在初始化的时候让该类=一个int值即可。又如Date的构造函数有三个形参,那么用花括号把三个数据括起来进行赋值即可。类类型之间也可以进行隐式类型转换,只需要有相对应的构造函数重载配合即可。
class A
{
public:
A(int x)
{
a = x;
}
private:
int a;
};
class Date
{
public:
Date(int year, int month, int day)
:_year(year)
,_month(month)
{}
private:
int _year;
int _month;
int _day = 2;
};
int main()
{
A a = 1;
Date d = { 1,2,3 };
}
static成员
用static修饰的成员变量,称为静态成员变量,静态成员变量是为类内所有对象公有,不属于某个对象,存放在静态区里面,如果想要初始化静态成员变量,则需要在类外进行初始化。
用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针,静态成员函数可以调用其他静态成员变量,但是不能访问非静态的成员变量。而非静态成员函数则可以访问所有非静态成员变量和静态成员变量。
如果想要在外部访问静态成员,突破类域可以通过类名::静态成员或者对象.静态成员来访问。但是请注意,静态成员也是类的成员,仍然受private protected public访问限定符的限制。
静态成员变量不能再声明位置给缺省值初始化,因为缺省值是作用于初始化列表,而静态成员变量不属于某个对象,他的初始化在外部而不在初始化列表。
class A
{
public:
A(int x)
{
a = x;
}
static void Print()
{
cout << b << endl;
}
private:
int a;
static int b;
};
友元
友元分为友元函数和友元类,它提供了一种突破类访问限定符的方式,使得外部函数能够使用类内变量。具体就是,在函数声明或类声明前面加一个friend,并把友元声明放在类里面。一个函数可以是多个类的友元函数,友元类中的成员函数都可以是另一个类的友元声明,都可以访问另一个类的私有与保护成员。谁,是谁的友元,谁,就能被谁访问。
友元类的关系是单向的,不具有交换性,如A是B的友元类,但是B不是A的友元类。友元也不具有传递性,如A是B的友元,B是C的友元,那么A不会是C的友元。
内部类
如果,我们把一个类定义在另一个类里面,我们就把这个类叫做内部类,内部类是独立的类,他只是受外部类类域限制和访问限定符限定,他不是外部类的一个对象。内部类默认就是外部类的友元类。如果我们实现A类就是为了给B类用,那我们就可以把A类定义为B的内部类,如果再把他放到private或者protected,这个内部类就是外部类的私有类。
class A
{
public:
A( int c)
:c(c)
{
B bb = (1,2);
}
private:
class B
{
public:
B(int a = 1, int b = 2)
:x(a)
,y(b)
{
A aa(1);
cout << aa.c << endl;
}
private:
int x;
int y;
};
int c;
};
int main()
{
A a(1);
return 0;
}
匿名函数
用类型(实参)定义出来的对象叫做匿名对象,一般用于简单应用使用,其生命周期只有一行。