在创建对象时,编译器会调用构造函数对对象进行初始化工作。对象的初始化有两种方式,一种是构造函数体赋值另一个是初始化列表。
构造函数体赋值
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
初始化列表
初始化列表以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
#1 每个成员变量在初始化列表中只能出现一次(只能初始化一次)
#2 类中包含以下成员,必须放在初始化列表位置进行初始化
# 引用成员变量
# const成员变量
引用和const都是必须在定义的时候初始化
# 自定义类型成员且该类没有默认构造时
#3 初始化列表的初始化顺序是在类中的声明次序
与其在初始化列表中的先后次序无关
class Test2
{
public:
Test2(int a)
{
_a = a;
}
private:
int _a;
};
class Test1
{
public:
Test1(int a, int& b, int c, int test)
:_a(a)
, _b(b)
, _c(c)
, _test2(test)
{}
private:
int _a;
int& _b;
const int _c;
Test2 _test2;
};
静态成员
静态成员变量
成员变量属于每一个类对象,储存在对象里面。静态成员变量属于类的每个对象,是共享的,存储在静态区。静态成员变量不能给缺省值,因为静态成员变量不存储在对象里面所以不走初始化。静态成员变量需要在类外面定义。
静态成员函数
静态成员函数没有this指针,指定类域和访问限定符就可以访问。
非静态成员可以调用静态成员,静态成员不能调用静态成员,因为非静态成员有this指针,需要指定类域。
class A
{
public:
static int TestA()
{
return _b;
}
private:
int _a = 0;
static int _b;
};
int A::_b = 0;
友元
友元函数
#1 友元函数可以访问类的私有和保护成员,但不是类的成员函数。
#2 友元不能使用 const 修饰,友元函数可以在类定义里的任何地方声明,不受类访问限定符限制。
#3 一个函数可以是多个类的友元函数
#4 友元函数的调用与普通函数的调用原理相同
class A
{
public:
friend int TestA(A& A);
private:
int _a = 0;
static int _b;
};
int TestA(A& A)
{
A._a += 1;
return A._a;
}
友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
#1 友元关系是单向的,不具有交换性。
#2 友元关系不能传递。
#3 友元关系不能继承
内部类
如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
内部类就是外部类的天生友元,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中所有成员。但是外部类不是内部类的友元。
#1 内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名
#2 sizeof(外部类)=外部类,和内部类没有任何关系
#3 内部类受外部类的访问控制限定符修饰(public,private,protected)
匿名对象
匿名对象一般适用于只调用一次的场景,且匿名对象即用即销毁,生命周期只在当前行。匿名对象具有常性。
class A
{
public:
A(int a)
{
_a = a;
}
void print()
{
cout << "666" << endl;
}
private:
int _a = 0;
};
int main()
{
A a(1);
A(2);
a.print();
A(2).print();
return 0;
}
匿名对象在 const 引用了过后,会延长它的声明周期,生命周期在当前函数局部域。
int main()
{
const A& ra = A(1);
return 0;
}