类和对象(下)

**【本节目标】
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值