C++类与对象下
构造函数:
1.构造函数体赋值
对于函数体的赋值,我们常见的都是在函数体内进行赋值.如下:
class Date{
public:
Date(int year,int month,int day){
_year=year;
_month=month; //这就是比较经典的赋值了
_day=day;
}
private:
int _year;
int _month;
int _day;
};
虽然上面构造函数,调用之后已经有了一个初始值,但是并不能将其称之为初始化,只能为赋初值,不能为初始化,因为初始化只能初始化一次,而成员函数内部可以进行多次的赋值.
2.初始化列表
这是一个新的概念,初始化列表,是以冒号开始,用逗号进行分割,且每个成员变量后面跟一个括号中的初始值或表达式.
class Date{
public:
Date(int year, int month, int day)
//====初始化列表: 真正初始化的位置
//在构造列表写完的时候初始化已经完成了
:_year(year)
, _month(month)
, _day(day)
//没有写这个初始化列表的时候就是一个随机值
{
//不是初始化
//赋值的地方
/*_year = year;
_month = month;
_day = day;*/
}
private:
int _year;
int _month;
int _day;
};
成员函数中,在大括号外面的才是真正初始化的地方!
全缺省默认构造
Time(int hour=1, int minute=5, int second=30) //全缺省默认构造
:_hour(hour)
, _minute(minute) //真正赋予初始化的地方
, _second(second)
{
//内部不是初始化,只是对随机值的一个赋值
cout << "Time()" << endl;
}
特点:
1)每个成员变量在初始化列表中只能出现一次
2)类中包含以下成员,必须放在初始化列表中进行初始化:
----引用成员变量
----const成员变量
----自定义类型成员(该类没有默认构造函数)
3)尽量在初始化列表中进行初始化,对于自定义变量来说,一定要在初始化列表中进行初始化
4)成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
例题:执行当前程序,看输出的是什么?
class A {
public:
//A(int a)
// :_a1(_a2) //这样写刚好将值进行链式的赋予,都为1
// , _a2(a)
A(int a)
:_a1(a)
, _a2(_a1) //逆序,进行初始化,从下往上
//在未进行赋值的时候,所有的都是随机值
{}
void Print() {
cout << _a1 << " " << _a2 << endl;
}
private:
int _a2;
int _a1;
};
void test4() {
A aa(1);
aa.Print();
}
具体理解:
3.explicit关键字
加入explicit可以禁止 单参构造隐式类型转换,单参构造隐试类型转换可就是,就是对于单个参数对其进行赋值的话会直接报错,需要分布进行.
class A{
public:
explicit A(int a); //====加入explicit可以禁止 单参构造隐式类型转换
A(int a)
:_a(a)
{
cout << "A(int)" << endl;
}
private:
int _a;
};
void test(){
A aobj(10); //简单构造
A aobj2 = aobj; //拷贝构造
A aobj3 = A(20);
//===============================================================
A aobj4 = 40; //先创建匿名对象,然后调用赋值运算符,将匿名
//对象的内容赋予aobj3
//单参构造隐式类型转换
//如果定义了explicit时这里就会报错!!!!!
}
static成员:
1.概念
在static修饰成员变量的时候,成为类的静态成员.利用static修饰成员函数,称之为静态成员函数,静态的成员变量一定要在类外进行初始化.
class A{
public:
A(){
++_count;
}
A(const A& a){
++_count;
}
//this指针:指向当前调用此函数的对象
//====static成员函数不包含this指针
//因为static函数可以通过类名访问,没有对象,this没有指向
static int getCount(){
//缺少this指针,不能调用非static成员函数
//fun();
return _count;
}
//普通的成员函数包含this 指针
void fun(){
//可以调用static成员函数
this->getCount();
cout << "fun()" << endl;
}
//private:
//static成员属于所有对象
//static成员变量: 必须在类外进行初始化
static int _count;
};
2.特性
1.静态成员可以在所有的类中进行调用.
2.静态成员变量必须在类外进行定义
3.类的静态成员可以用 “::” 来对静态成员进行访问
int A::_count = 0;
4.静态成员函数没有隐藏函数this指针
5.静态成员和类的普通成员也是一样的,都有三种访问级别
C++初始化(new)
C++11支持非静态成员变量在声明时进行初始化赋值,这里不是初始化,就是给予一个缺省值而已.
class A{
public:
A(int a=1)
:_a(a)
{}
private:
//C++11新的初始化方式,在成员变量生命的时候,给一个缺省值
//此处声明的缺省值,在没有其他值可选的时候,才会用
//仅限于非static成员
int _a=0;
//int _a; //随机值
//static int _b = 10; 报错,静态的必须在类外进行初始化
};
友元:
1.友元函数
有元函数就是将一个成员函数定义成有元,让其可以访问私有类
class Date{
public:
//有元函数的声明:此函数可以访问当前类的私有成员
//不属于类的成员
//可以放在类的任何地方,不影响使用
friend void operator<<(ostream& _cout, const Date& d); //当在这里进行friend声明以后,她就可以访问private所在内部的数据
Date(int y = 1, int m = 2, int d = 3)
:_y(y)
, _m(m)
, _d(d)
{}
//可访问私有成员
void operator<<(ostream& _cout){
_cout << _y << "-" << _m << "-" << _d << endl; //访问后可以输出
}
private:
int _y;
int _m;
int _d;
};
1.友元函数可以访问私有类成员,但并不是类的成员函数
2.友元函数不能用const修饰
3.友元函数可以在任何部位进行声明,可以定义在类内部的任何地方
4.一个函数可以是多个类的友元函数
5.友元函数的调用和普通函数基本一致.
例题:日期类输入输出
对于友元函数来说,我们主要就是利用它来访问在类中的私有部分,将其内部的数据进行表示出来,但是对于日期类的输入和输出我们都是要把年月日进行依次输出,所以我们要在这里改变>>和<<两个符号的含义,让它可以执行对于日期类代码的正常的输入和输出,如下:
1.第一部分写一个类,并且进行有元定义,可以让外部函数对private内部进行访问
2.在外部定义出对应的函数
3.对其进行调用即可
class Date{
//友元函数的声明
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, Date& d);
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{
}
private:
int _year;
int _month;
int _day;
};
//返回值ostream可以支持连续的输出
ostream& operator<<(ostream& _cout, const Date& d) {
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
istream& operator>>(istream& _cin, Date& d){
_cin >> d._year >> d._month >> d._day;
return _cin;
}
//==输出
void test(){
Date d(2021, 3, 7);
//简写形式
cout << d << endl;
//完整形式
//operator<<(cout, d);
连续输出
//cout << d << endl;
//operator<<(cout, d)<<endl;
cin >> d; //输入操作,首先你先要将其定义出来
cout << d << endl << d << endl << d << endl;;
}
这就是有元的具体作用
2.友元类
就是将一个类定义成有元,可以对其内部的类内部的private进行调用.
通过两个类的连接就可以利用Date对Time中的Private进行调用
class Date;
class Time
{
friend class Date; //有元声明
public:
Time(int hour, int minute, int second)
: _hour(hour)
, _minute(minute)
, _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1) //缺省默认构造
: _year(year)
, _month(month)
, _day(day)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
_t._hour = hour;
_t._minute = minute;
_t.second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
具体调用我就不详细写了,大家自己多看看,自己写.
内部类
内部类就是在一个类中,紧接着定义出另外一个类
1.内部类就是外部类的友元类
2.内部类可以定义在外部类的public、protected、private都可以
3.注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名
4.sizeof(外部类)=外部类,和内部类没有关系
class A{
public:
//有元类的声明
friend class C;
//==内部类
//==============================
class B{
public:
void setA(A& a){
a._a = _b;
}
private:
int _b = 2;
};
//===============================
private:
int _a = 1;
static int _sa; //定义静态成员变量
};
//有元类
class C{
public:
void setA(A& a){ //在有元后对A中的进行调用
a._a = _c;
a._sa = 20;
A::_sa = 5;
}
private:
int _c = 3;
};
int A::_sa = 10; //对A中的静态变量进行赋值
你要明白A的类和A的内部类没有从属关系,只是放在一起而已,内部并不是包含关系的!
举例:
判断内部的字节大小,你可以直接运行,从而证明两者没有从属关系.
void test(){
//判断是否从属
int a = sizeof(A);
int b = sizeof(A::B);
cout << a <<"--"<< b << endl;
}
内容又点多,可能我在解释的方面还比够完善,当我有了更加深入的理解以后会补充,大家一起加油!!!多敲代码!!!