目录
1.explicit关键字
构造函数不仅可以构造与初始化对象,对于接收单个参数的构造函数,还具有类型转换的作用。接收单个参数的构造函数具体表现:
- 构造函数只有一个参数
- 构造函数有多个参数,除第一个参数没有默认值外,其余参数都有默认值
- 全缺省构造函数
class Date
{
public:
//1.单参构造函数,没有使用explicit修饰,具有类型转换作用
//explicit修饰构造函数,禁止类型转换--explicit去掉之后,代码可以编译
explicit Date(int year)
:_year(year)
{}
//2.虽然有多个参数,但是创建对象时后两个参数可以不,没有使用explicit修饰
//,具有类型转换作用
//explicit修饰构造函数,禁止类型转换
explicit Date(int year, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
{}
Date& operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2024);
//用一个整型变量给日期类型对象赋值
//实际编译器背后会用2024构造一个无名对象,最后用无名对象给d1进行赋值
d1 = 2024;
//将1屏蔽掉,2放开时编译失败,因为explicit修饰构造函数,禁止
//单构造函数类型转换的作用
}
上述代码可读性不是很好,用explicit修饰构造函数,将会禁止构造函数的隐式转换
2.static成员
2.1概念
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化
实现一个类,计算程序中创建出了多少个类对象?
class A
{
public:
A()
{
++_scount;
}
A(const A& t)
{
++_scount;
}
~A()
{
--_scount;
}
static int GetACount()
{
return _scount;
}
private:
static int _scount;
};
int A::_scount = 0;
int main()
{
cout << A::GetACount() << endl;//0
A a1, a2;
A a3(a1);
cout << A::GetACount() << endl;//3
return 0;
}
2.2特性
- 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
- 静态成员变量必须在类外面定义,定义时不添加static关键字,类中只是声明
- 类静态成员即可用类名 ::静态成员或者对象.静态成员来访问
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
- 静态成员也是类的成员,受public,protected,private访问限定符的限制
class A
{
public:
A()
{
++_scount;
}
A(const A& t)
{
++_scount;
}
~A()
{
--_scount;
}
void Func1()
{
//非静态能否调用静态:可以
GetACount();
}
void Func2()
{
++_a1;
}
//没有this指针,指定类域和访问限定符就可以访问
static int GetACount()
{
//静态能否调用非静态:不可以。非静态的成员函数调用需要this指针,我没有this
//Func2();
//_a1++;
return _scount;
}
private:
//成员变量 -- 属于每个一个类对象,存储对象里面
int _a1 = 1;
int _a2 = 2;
//静态成员变量 -- 属于类,属于类的每个对象共享,存储在静态区
static int _scount;
};
//全局位置,类外面定义
int A::_scount = 0;