初始化列表也是对类成员变量进初始化的一种方式。构造函数初始化成员变量主要是在函数体内赋值的,初始化列表的使用方式是以一个冒号开始,接着是以逗号分隔各成员变量的数据列表。每个成员变量后面跟一个放在括号中的初始值或表达式。
🌿 每个成员变量在初始化列表中只能出现一次 🌿 引用成员变量,const成员变量,没有默认默认构造函数的类类型成员变量必须放在初始化列表中初始化,否则会编译报错。 🌿 C++11支持在成员变量声明位置给缺省值。 🌿 要尽量使用初始化列表进行初始化,因为那些没有在初始化列表初始化的成员也会走初始化列表进行初始化。如果成员变量在成员变量声明的位置给了缺省值,初始化列表会用这个值进行初始化。若没有缺省值,对于没有显示在初始化列表进行初始化的内置类型成员是否初始化取决于编译器,对于类类型成员会调用这个成员的默认构造函数,若没有默认构造函数就会编译报错。 🌿初始化列表中的成员会按照成员声明的先后顺序初始化,与成员在初始化列表中的先后顺序无关。
📌总结:
1>无论是否显示写初始化列表,每个构造函数都有初始化列表。
2>无论是否在初始化列表显示初始化,每个成员变量都要走初始化列表初始化。
📙c++支持内置类型隐式类型转换为类类型对象,需要有内置类型为参数的构造函数。
📙构造函数前面+explicit
就不再支持隐式类型转换。
📙类类型对象间也可以隐式转换,但是需要相应的构造函数。
#include<iostream>
using namespace std;
class A
{
public:
A(int a1)
:_a1(a1)
{}
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{}
int Get()const
{
return _a1 + _a2;
}
private:
int _a1 = 1;
int _a2 = 2;
};
class B
{
public:
B(const A& a)
:_b(a.Get())
{}
private:
int _b = 0;
};
int main()
{
A aa1 = 1; //1构造一个A的临时对象,在用这个对象拷贝构造aa1
//编译器将连续构造+拷贝构造优化为直接构造
A aa3 = { 2,2 };
B b = aa3; // aa3隐式类型转换为b
return 0;
}
🔖static
修饰的成员变量称为静态成员变量,静态成员变量一定要在类外面进行初始化.
🔖静态成员变量为所有类对象共享,不属于某个具体的类,不存在对象中,存放在静态区。
🔖static
修饰的函数称之为静态成员函数,静态成员函数没有this
指针。
🔖静态成员函数可以访问其他静态成员,但是不能访问非静态的, 因为无this
指针。
🔖非静态成员函数可以访问任意的静态成员函数和静态成员变量。
🔖静态成员也是类的成员,也受public,protected,private
访问限定符的限制。
🔖静态成员变量不能在声明位置给缺省值,因为缺省值是给初始化列表的,静态成员变量不属于某个对象,不走构造函数初始化列表。
友元分为友元函数和友元类,在函数声明或者类声明的前面加friend
并且把友元声明放到一个类里面。借助友元可以使得普通函数或者其他类中的成员函数可以访问到某个类的私有或者保护成员。
友元函数可以直接访问类的私有或者保护成员,它是定义在类外面的普通函数,它不属于任何类,但需要在类的定义中加以声明。
友元函数的声明格式:
friend 类型 函数名(形参)
#include<iostream>
using namespace std;
//前置声明
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;
func(aa,bb);
return 0;
}
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类的保护成员和私有成员。
友元类的声明格式:
friend class 类名
#include<iostream>
using namespace std;
class A
{
public:
friend class B; //声明友元类
void SetAge(int age)
{
_age = age;
}
private:
int _age;
};
class B
{
public:
void ShowAge(A a)
{
cout << a._age << endl;
}
};
int main()
{
A a;
a.SetAge(20);
B b;
b.ShowAge(a);
return 0;
}
如果没有在A的类中声明友元类B,则在B类中就不能访问A中的私有成员。 ⚠️友元类的关系是单向的,不具有交换性。 ⚠️友元类关系不能传递
友元会增加耦合度,破坏了类的封装性和隐藏性,所以不易多用。
内部类是一个定义在一个类内部的类,内部类可以访问外部类的私有成员。内部类默认是外部类的友元类。
#include<iostream>
using namespace std;
class A
{
public:
//B是A的内部类
class B
{
public:
void func(const A& a)
{
cout << a._year << endl; //B中可以访问A中的私有成员
cout << a._month << endl;
}
};
private:
int _year = 1;
int _month = 2;
};
int main()
{
A a;
A::B b;
b.func(a);
return 0;
}
用类型(实参)
定义出来的对象叫做匿名对象。
匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可时可以用匿名对象。
#include<iostream>
using namespace std;
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A aa1;
//A aa1(); 不能这样定义对象,因为编译器无法识别是一个函数声明还是对象定义
A();//可以这样定义
A(1);//匿名对象的生命周期只有这一行,这一行结束会自动调用析构函数
return 0;
}