**【本节目标】
1.static成员
2.C++11 的成员初始化新玩法。
3. 友元
4 .内部类
5.Date类(例子)
**
1.static成员
1.1概念:声明为static的类成员称为类的静态成员;
用static修饰的成员变量,称之为静态成员变量,用static修饰的
成员函数,称之为静态成员函数。
静态的成员变量一定要在类外进行初始化。(初始化不用加static)
//实现一个类,计算程序中创建出多少对象?
class Date
{
public:
Date(int year, int month, int day)
:_year(year)
, _month(month)
, _day(day)
{
_count++;
}
~Date()
{
_count--;
}
Date(Date& d)
: _year(d._year)
, _month(d._month)
, _day(d._day)
{
_count++;
}//拷贝构造函数初始化
void TestFunc()
{
_day++;
cout << _count << endl;
}
//静态成员函数
static int GetCount()
{
return _count;
}
private:
int _year;
int _day;
int _month;
static int _count;
};
//静态成员变量初始化
int Date::_count = 0;
void TestDate()
{
Date d3(2019, 9, 16);
Date d4(d3);
Date d5(2019, 9, 12);
cout << Date::GetCount() << endl;
//非静态成员引用必须用特定对象引用
//静态成员函数可以用类类型引用
}
int main()
{
Date d1(2019, 9, 15);
Date d2(d1);
cout << d1.GetCount() << endl;
TestDate();
return 0;
}
1.2特性:
1.静态成员为所有类对象所共享,不属于某个具体的实例。
(不会影响类对象的大小sizeof的结果,存储位置:静态区)
2. 静态成员变量必须在类外定义,定义时不添加static关键字。
3. 类静态成员即可用 :类名::静态成员/对象.静态成员来访问
4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
5. 静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值。
(静态成员函数不能调用非静态成员函数-没有this指针;
非静态成员函数可以调用类的静态成员函数。】
2.C++11 的成员初始化新玩法。
C++11支持非静态成员变量在声明时进行初始化赋值,但是要注意这里不是初始化,这里是给声明的成员变量缺省值。
class B
{
public:
B(int b=0)
:_b(b)
{}
int _b;
};
class A
{
public:
void Print()
{
cout << a << endl;
cout << b._b << endl;
cout << p << endl;
}
private:
//非静态成员变量,可以在成员声明时给缺省值。
int a = 10;
B b = 20;
int *p = (int *)malloc(4);
static int n;
};
int A::n = 10;
int main()
{
A a;
a.Print();
return 0;
}
3.友元
友元分为:友元函数和友元类。
友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多
用。
3.1 友元函数
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声
明,声明时需要加friend关键字。
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, const Date& d);
public:
Date(int year=89, int month=0, int day=0)
:_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, const Date& d)
{
_cin >> d._year;
_cin >> d._month;
_cin >> d._day;
return _cin;
}
int main()
{
Date d1(1990, 4, 5);
Date d;
cin >> d1;
cout << d1 << endl;
return 0;
}
说明:
1.友元函数可访问类的私有成员,但不是类的成员函数
2.友元函数不能用const修饰
3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制
一个函数可以是多个类的友元函数
4.友元函数的调用与普通函数的调用和原理相同
3.3友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
说明:1.友元关系是单向的,不具有交换性。
2.友元关系不能传递。
class Date; // 前置声明
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变
量
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;
};
4.内部类
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。
注意:此时这个内部类是一个独立的类。不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。
内部类就是外部类的有元类。内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
特性:
1.内部类可以定义在外部类的public,protcted,private都是可以的。
2.内部类可以直接访问外部类中的static,枚举成员,不需要外部类的对象/类名。
3.sizeof(外部类)=外部类,和内部类没有关系。
class A
{
public:
A(int a)
:_a(a)
{}
class B
{
public:
B(int b)
:_b(b)
{}
void TestFun()
{
A a(1);
a._a = 10;
A::_c = 10;
a._c = 2;
_c=12;//内部类可以直接访问外部类中的static,枚举成员,不需要外部类的对象/类名
}
private:
int _b;
};
private:
int _a;
static int _c;
};
int A::_c = 1;
int main()
{
A::B B(10);
//注意:内部类是一个独立的类,没有包含在外部类中
cout << sizeof(A) << endl;
return 0;
}
5.Date类(例子)
class Date
{
public:
Date(int year=1900, int month=1, int day=1)
:_year(year)
, _month(month)
, _day(day)
{
//如果所输入的年不符合实际要求进行初始化
if (!(_year>0&&
_month>0&&_month<13&&
_day>0 && _day<GetMonthOfYear(_year, _month)))
{
_year = 1;
_month = 1;
_day = 1;
}
}
Date(const Date&d)
:_year(d._year)
, _month(d._month)
, _day(d._day)
{}
//=
Date& operator=(const Date d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
//+
Date operator+(int days)
{
if (days < 0)
{
return *this - (0 - days);
}
Date tmp(*this);
tmp._day += days;
int daysofMonth = 0;
while (tmp._day > (daysofMonth = tmp.GetMonthOfYear(tmp._year, tmp._month)))
{
tmp._day -= daysofMonth;
tmp._month++;
if (tmp._month > 12)
{
tmp._year++;
tmp._month = 1;
}
}
return tmp;
}
Date operator-(int days)
{
if (days < 0)
{
return *this + (0 - days);
}
Date tmp(*this);
tmp._day -= days;
while (tmp._day <= 0)
{
tmp._month--;
if (tmp._month < 0)
{
tmp._year--;
tmp._month = 12;
}
tmp._day += tmp.GetMonthOfYear(tmp._year, tmp._month);
}
return tmp;
}
int operator-(const Date d)//两个日期间相差了多少天
{
Date minDate(*this);
Date maxDate(d);
if (*this > d)
{
swap(minDate, maxDate);
}
size_t count = 0;
while (minDate != maxDate)
{
count++;
minDate++;
}
return count;
}
Date& operator++()// 前置++
{
*this = *this + 1;
return *this;
}
Date operator++(int)//后置++,先返回再运算 注意返回值不能用引用
{
Date tmp(*this);
*this = *this + 1;
return tmp;
}
Date& operator--()
{
*this = *this-1;
return *this;
}
Date operator--(int)
{
Date tmp(*this);
*this = *this - 1;
return tmp;
}
bool operator>(const Date d)
{
if (_year > d._year
|| _year == d._year&&_month > d._month
|| _year == d._year&&_month == d._month&&_day > d._day)
{
return true;
}
return false;
}
bool operator==(const Date d)
{
if (_year == d._year&&_month == d._month&&_day == d._day)
{
return true;
}
return false;
}
bool operator!=(const Date d)
{
return !(*this == d);
}
friend ostream& operator<<(ostream&_cout, const Date &d)
{
_cout << d._year << "-" << d._month << "-" << d._day << endl;
return _cout;
}
void swap(Date& minDate, Date& maxDate)
{
Date tmp;
tmp = minDate;
minDate = maxDate;
maxDate = tmp;
}
int GetMonthOfYear(int year, int month)
{
int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month == 2&&IsLeapYear(year))
{
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
days[_month] = 29;
}
}
return days[month];
}
bool IsLeapYear(int year)
{
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
return true;
}
return false;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2019,9,18);
Date d2(2000, 9, 1);
cout << d2 - d1 << endl;
d1 = d1 - 999;
//d1 = d1 + 100;
//d1 + 100;
cout << d1<< endl;
system("pause");
return 0;
}