初始化列表
初始化列表——>成员变量定义的地方
初始化列表:以冒号开始,后面跟着成员变量,以逗号为间隔,每个成员变量后面跟一个放在括号内的初始值或者表达式。
class Test
{
public:
Test()
//构造函数初始化列表
a(10),
b(20)
{ }
Test()
//构造函数内部赋值
{
a=10;
b=20;
}
private:
int a;//这里只是声明,不是定义,定义是会开辟一块空间来存储变量值的
int b;
};
上面这两个构造函数的结果是一致的,但在功能上却不相同。有初始化列表的构造函数是对成员变量进行了初始化,而另一个是对成员变量进行赋值。
初始化只能初始化一次,但赋值可以多次。
初始化化和赋值对于内置类型并没有什么大的区别,但对于自定义类类型和引用成员变量还有const成员变量时必须采用初始化列表进行初始化。
1.引用成员:引用类型必须在定义的时候初始化
2. const成员变量:const修饰的变量不能被改变其内容,所以你只有初始化的时候能给值
3. 自定义类类型:在进入构造函数体里面是,所以成员变量就已经定义并初始化完成,函数体内部只是赋值操作,所以当某个成员是自定义类类型的话,其类内部未有定义默认构造函数时,就必须对该成员进行初始化
编译器会生成默认构造函数,但c++并未规定类一定会有生成默认构造函数
初始化列表的使用
初始化列表在使用时要注意,每个成员只能在初始化列表出现一次(初始化只能初始化一次),类成员包含引用类型、const修饰类型、自定义类类型时必须放在初始化列表初始化,成员变量的声明次序就是初始化次序,与其在初始化列表的顺序无关。
class test
{
public:
test(int x)
: b(x),
a(b)
{}
void prin()
{
cout<<"b="<<b<<"--"<<"a="<<a<<endl;
}
private:
int a;
int b;
};
int main()
{
test t;
t(1);
t. prin();
return 0;
}
运行结果为:b=1–a=随机值;
总结:3. 尽量使用初始化列表初始化,因为不管是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
友元
友元分为友元函数和友元类
1.友元函数
类的私有成员受类的访问限定符保护,只能在类的成员函数内部访问。在其他地方想访问对象的私有成员只能通过类提供的接口间接地进行。但我们通过友元就可以在类的外部直接访问对象的私有成员。
在定义一个类的时候,可以把一些函数(包括全局函数和其他类成员函数)声明为友元,那这些函数就会成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。
- 将全局函数声明为友元:
friend 返回值类型 函数名(参数列表)
- 将其他类的成员函数声明为友元 :
friend 返回值类型 其他类的类名::成员函数名(参数列表)
int ADD()
{
return _a1+_a2;//可以访问类中的私有成员
}
class A
{
public:
friend int ADD();//声明为友元函数
int RetMax()
{
_a1+=_b1;//可以访问其他类中的私有成员了
_a2+=_b2;
return _a1>_a2?_a1:_a2;
}
private:
//不能把类中的私有成员函数声明为友元
int RetMin()
{
return _a1<_a2?_a1:_a2;
}
int _a1;
int _a2;
};
class b
{
public:
friend int A::RetMax();//声明其他类成员函数为友元
private:
int _b1;
int _b2;
};
友元函数可以访问类的私有和保护成员,但它不是类的成员函数
友元函数不能用const修饰
友元函数可以在类定义的任何地方声明,不受类的访问限定符限制
一个函数可以是多个类的友元函数
友元函数的调用跟普通函数的调用一样
2.友元类
友元类的所以成员函数都是另一个类的友元函数,都可以访问另一个类中的成员。
class A;//前置声明
class B
{
friend class A;//声明为A友元类
public:
private:
int _a1;
int _a2;
};
class A
{
public:
A A1;
void ts()
{
A1._a1+=100;//因为A是B的友元类,所以可以直接访问其私有成员
}
};
友元关系是不具有传递性的。(A是B的友元,B是C的友元,A就一定是C的友元是错误的)
友元关系是单向的,不具有交互性。(A是B的友元,A可以访问B的私有成员,但想在类B中访问A的私有成员就不行)
3.内部类
1.概念
如果一个类定义在另一个类的内部,这个类就叫做内部类。而这个内部类是一个独立的类,它不属于外部类。也不能通过外部类的对象去调用内部类,外部类对内部类没有任何特殊的访问权限
内部类就是外部类的友元类,注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类的所有成员,但外部类不是内部类的友元。
2.特性
class A
{
public:
A()
: n=20
{}
private:
static int i;
int n;
public:
class B
{
void ts(const A& a)
{
cout<<i<<endl;//ok
cout<<a::n<<endl//ok
}
}
};
int A::i=10;//静态成员变量须在类外部进行初始化
int main()
{
A::B b;
b.ts(A());
}
- 内部类可以定义在外部类的公开、私有、保护都是可以的;
- 内部类可以直接访问外部类中的static/枚举成员,不需要外部类的对象/类名;
- 计算外部类大小时,跟内部类没有关系;
4.static成员
1.概念
声明为static的类成员称为类的静态成员;用static修饰的成员变量称之为静态成员变量,
用static修饰的成员函数称之为静态成员函数。静态的成员变量一定要在类外进行初始化;
特性
- 静态成员为所有类对象共享,不属于某个具体的实例化对象;
- 静态成员函数必须在类外定义,定义时不添加static关键字;
- 类静态成员可用类名::静态成员或对象.静态成员来访问;
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员;
- 静态成员和类的普通成员一样,也有public、protected、private这3种访问级别,也可以有返回值;
5.explicit关键字
用来修饰构造函数,禁止单参构造函数的隐式转换,表明该函数是显式的。C++类的构造函数如果只有一个参数,在编译的时候就会有一个缺省的转换操作,将该构造函数对应数据类型的数据转换为该类对象;
A a1;//定义一个A类的对象
a1=10;//用一个整型给它赋值,实际编译器会用10构造一个无名对象,最后用无名对象给a1对象赋值
运行结果
图片出处https://www.cnblogs.com/skyzu2333/p/15063565.html