在C++初阶(4)中,我们具体实现了Date日期类。今天我想继续往下讲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)
{}
private:
int _year;
int _month;
int _day;
};
但注意,有三种成员变量必须使用初始化列表初始化。
- const变量
- 引用
初始化列表是成员变量的定义阶段,而const和引用类型的变量必须在定义后立马初始化,所以必须放在初始化列表初始化
3.没有默认构造函数的自定义类型变量 举例说明:
class A
{
};
class Date
{
public:
Date(int year, int month, int day)
:_n(10)
, _ref(year)
, _a(1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
const int n;
int& ref;
A _a;
};
另外,成员变量在初始化列表中的初始化顺序由类中的声明次序决定,与其在初始化列表中的先后顺序无关 因此建议:在类中声明的成员变量的顺序与初始化列表中的顺序保持一致 举例说明:
class A
{
private:
int _a2;
int _a1;
public:
A(int a)
:_a1(a)
, _a2(_a1)
{}
void Print()
{
cout << _a1 << "" << _a2 << endl;
}
};
int main()
{
A.aa(1);
aa.Print();
return 0;
}
A.1 1 B.程序崩溃 C.编译不通过 D.1 随机值
二、Static ·static成员变量
class A
{
private:
static int n;
};
int A::_n = 0;
static变量存在于静态区,属于整个类,不属于某个单独的对象。 因此静态成员不能在构造函数里初始化,要在类外单独初始化,且前面不加static
由于静态成员属于整个类,因此既可以通过类名访问,也可以通过类的某个对象访问
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year = 2021, int month = 8, int day = 15)
{
_year = year;
_month = month;
_day = day;
}
static int n;
};
int Date::n = 2021;
int main()
{
Date d1(2021,8,19);
Date d2(d1);
Date d3(d2);
cout << Date::n << d1.n << d2.n << d3.n << endl;
return 0;
}
·静态成员函数 静态成员函数的特点: 另外,静态成员函数不能调用非静态成员函数,非静态成员函数能调用静态成员函数
举例说明:
class A
{
private:
int a;
static int n;
public:
static int Get_n()
{
a = 1;
return n;
}
};
下面,我们通过一个例题,来更好地了解静态成员函数的作用 例题1:
求1+2+3+……10,不能使用乘除法,for while if wlse switch case
class Add
{
public:
Add()
{
sum += n;
++n;
}
Add(const Add& a)
{
++n;
}
void Print()
{
cout << Add::sum << endl;
}
private:
static int n;
static int sum;
};
int Add::n = 1;
int Add::sum = 0;
int main()
{
Add aa[10];
aa[0].Print();
return 0;
}
三、友元 ·友元函数
声明形式: friend 返回类型 函数名(参数列表) 特点:
- 友元函数可以访问类的私有和保护成员,但并不是类的成员函数
- 友元函数不能用const修饰
- 友元函数不受类的访问限定符控制,可以在类的任何地方声明
- 一个函数可以同时是多个类的友元函数
- 友元函数的嗲用与普通函数的调用和原理相同
我们通过重载<<和>>来举例说明: 重载<<时,要实现连续输出,必须是cout<<变量的形式。如果设计成普通成员函数,第一个参数默认为this指针,调用时只能写成变量>>cout*,就没法连续输出了 另外,函数的返回类型应是ostream类的引用
重载>>同理。
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year = 0, int month = 0, int day = 0)
{
this->_year = year;
this->_month = month;
this->_day = day;
}
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
};
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
int main()
{
Date d1;
Date d2(2021, 5, 25);
cin >> d1 >> d2;
cout << d1 << d2;
return 0;
}
·友元类 特点:
- 友元关系是单向的,不具有交换性
如A是B的友元类,则A中所有的成员函数都是B的友元函数,都可以访问B中的非公有成员。但反之就不行 - 友元关系不能传递
B是A的友元,C是B的友元,不能说明C是A的友元
举例说明:
class Time
{
friend class Date;
private:
int _hour;
int _minute;
int _second;
public:
Time(int hour = 0,int minute=0,int second=0)
:_hour(hour)
,_minute(minute)
,_second(second)
{}
};
class Date
{
private:
int _year;
int _month;
int _day;
Time _t;
public:
Date(int year=2021,int month=0,int day=0)
: _year(year)
,_month(month)
,_day(day)
{
_t._hour = 1;
}
void SetTimOfDate(int hour, int minute, int second)
{
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
};
但是要说明的是:友元是一种破坏封装的行为。因此一般情况下,不建议使用友元 。
|