构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。(c++98开始支持)
对于多个参数的构造函数也支持类型转换的作用!(c++11开始支持)
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化
1.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
2.静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
3.类静态成员即可用类名静态成员或者对象静态成员来访问
4.静态成员函数没有隐藏的this指针,不能访问任何非静态成员
5.静态成员也是类的成员,受public、protected、private 访问限定符的限制
下面的代码段里包含我对static成员的理解
//局部变量-局部作用域-栈
//全局变量-全局域
// 类变量-类域
//
//全局static-作用域:全局
//局部static-作用域:局部
// 类static-作用域:类 ||static成员变量:属于类,且类的每个对象共享
// 这三类的生命周期-全局
//
class A
{
public:
A(int a = 0)
:_a(a)
{
++N;
}
//静态成员函数:没有this指针,只能访问静态成员
static int GetN()
{
return N;
}
A(const A& aa)
:_a(aa._a)
{
++N;
}
private:
int _a;
//生命周期是全局的,但作用域是类域-保护N不被修改
static int N;//声明
};
//定义-不需要static修饰
int A::N = 0;
void F1(A aa)//传值传参-拷贝构造//引用返回-不构造
{
}
A F2()
{
A aa;//调用A的构造函数-构造aa
return aa;//返回A类型-拷贝构造一份临时变量返回
}
int main()
{
A aa1(1);//构造-1
//A aa2 = 2;//构造-1
// A aa3 = aa1;//拷贝构造-1
F1(aa1);//拷贝构造-1
//F2();//构造+拷贝构造-2
//cout << A::N << endl;//N为类中公有对象可以这样访问
//cout << aa1.N << endl;//N为类中公有对象可以这样访问
// A*ptr=&aa1(nullptr);
// cout<N<
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
1.友元函数可访问类的私有和保护成员,但不是类的成员函数
2.友元函数不能用const修饰(友元函数没有this指针)
3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制
4.一个函数可以是多个类的友元函数
5.友元函数的调用与普通函数的调用原理相同
1.友元关系是单向的,不具有交换性。
2.友元关系不能传递
3.友元关系不能继承
class floort
{
friend class door;//声明door类函数是floort类函数的友元函数,door类函数可以访问floort类函数的私有成员
public:
floort (int floor = 1)
:_floor(floor)
{}
private:
int _floor;
};
class door
{
public:
door(int door = 1)
:_door(door)
{}
void findfloor(int door,int floor)
{
_t._floor = floor;//直接访问floort类的私有成员变量(floor)
_door = door;
}
private:
int _door;
floort _t;
};
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
在【外部】类(类A)外面访问内部类(类B)(类中类)必须要通过【外部】类(类A)-限制
内部类可以定义在外部类的public、protected、private都是可以的。
注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
sizeof(外部类)=外部类,和内部类没有任何关系。
class A
{
public:
//B天生是A的友元-可以访问A中的所有成员
class B
{
int _b;
};
private:
int _a;
};
int main()
{
cout << sizeof(A) << endl;//4个字节-只有_a的大小 ,B类中_b的大小不沾边
A aa;
// B bb;//不可以
A::B bb;//可以-访问B必须要通过A
return 0;
}
匿名对象的构造函数和析构函数的调用在同一行(调用完构造函数后自动调用析构函数)
class A {
public:
A(int a = 0)
:_a(a)
{
cout << "调用构造函数 A(int a)" << endl;
}
~A()
{
cout << "调用析构函数~A()" << endl;
}
private:
int _a;
};
class Solution {
public:
int Sum_Solution(int n) {
//...
return n;
}
};
A F()
{
//A tmp(10);
// return tmp;
return A(10);//匿名对象-上面两行合并成这一行
}
int main()
{//有名对象-生命周期局部域-main函数的域-析构函数在main函数末尾时调用
//A aa1(1);
//A aa2=aa1;
//匿名对象-生命周期只在这一行-析构函数在这一行结束时调用
// A();
// A aa3;aa3 = 3;
// A(3);//匿名对象-上面这行合并成这行
return 0;
}
在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。
class A {
public:
A(int a = 0)//构造函数
:_a(a)
{
cout << "调用构造函数A(int a)" << endl;
}
A(const A& aa)
:_a(aa._a)
{
cout << "调用拷贝构造函数A(const A& aa)" << endl;
}
A& operator=(const A& aa)
{
cout << "调用运算符重载函数A& operator=(const A& aa)" << endl;
if (this != &aa)
{
_a = aa._a;
}
return *this;
}
~A()
{
cout << "调用析构函数~A()" << endl;
}
private:
int _a;
};
void f1(A aa)
{}
A f2()//传值返回
{
A aa;//构造
return aa;//拷贝构造
}
A f3()
{
return A(10);
}
int main()
{
//A aa1 = 1;//A tmp(1) +A aa1(1)->优化为A aa1(1) ---构造+拷贝构造->构造
//A aa1;
//f1(aa1);//这两行是构造+拷贝构造
//f1(A(1));//构造+拷贝构造->优化:构造
//f2();//构造+拷贝构造
//A tmp = f2();//构造+拷贝构造+拷贝构造->优化:构造+拷贝构造
A tmp1 = f3();//构造+拷贝构造+拷贝构造->优化:构造
return 0;
}