P200  struct

考虑用一个struct实现date的概念:

struct Date {
  int d, m, y;
};
void init_date(Date& d, int, int, int); //初始化d
void add_year(Date& d, int n);          //d加n年
void add_month(Date& d, int n);         //d加n月
void add_day(Date& d, int n);           //d加n天

 

 

在日期类型与这些函数之间并没有任何显示的联系。可以通过将这些函数声明为成员,从而建立起这种联系: 

struct Date {
  int d, m, y;
  void init(int dd, int mm, int yy);    //初始化
  void add_year(int n);                 //加n年
  void add_month(int n);                //加n月
  void add_day(int n);                  //加n天
};

 

 

由于在不同的结构里,可能存在相同名字的成员函数,我们在定义成员函数时就必须给出有关结构的名字:

void Date::init(int dd, int mm, int yy) {
  d = dd;
  m = mm;
  y = yy;
}

 

 

 在成员函数里面,结构内部各个成员的名字都可以直接调用,不必显式地去引用某个对象。在这种情况下,这些名字所引用的就是该函数调用时所针对的那个对象的成员。

例如,如果today调用Date::init(), 那么m=mm将给today.m赋值。另一方面,如果为my_birthday调用Date::init(),那么m=mm就会给my_birthday.m赋值。

类的成员函数总知道它是为了哪个对象而调用的。

Date my_birthday;
void f() {
  Date today;
  today.init(16, 10, 1996);
  my_birthday.init(30, 12, 1950);

  Date tomorrow = today;
  //tomorrow.add_day(1);
}

 

 


 

 

P201

上述Date声明提供了一组操作Date的函数,然而,它并没有清楚地说明这些函数就是直接依赖于Date的表示的全部函数,而且也是仅有的能够直接访问Date类的对象的函数。(struct声明中没有私有成员的概念,非成员函数是禁止访问私有成员的)

class Date {
  int d, m, y;
public:
  void init(int dd, int mm, int yy);    //初始化
  void add_year(int n);                 //加n年
  void add_month(int n);                //加n月
  void add_day(int n);                  //加n天
};
inline void Date::add_year(int n) {     //正确:类的成员函数
  y += n;
}
void timewarp(Date& d) {                //错误:不是类的成员函数,Date::y为私有成员
  d.y -= 200;
}

 

 

P202  class

init()函数提供对类对象的初始化,可以用构造函数代替:

class Date {
  int d, m, y;
public:
  Date(int, int, int);                  //构造函数
  void add_year(int n);                 //加n年                                         
  void add_month(int n);                //加n月
  void add_day(int n);                  //加n天
};

 

如果构造函数要求参数,那么必须提供这些参数:

Date today = Date(23, 6, 1983);         //ok
Date xmax(25, 12, 1990);                //上句的简写形式
Date my_birthday;                     //错误:缺少初始式
Date release1_0(10, 12);              //错误:缺少第3个参数

 

 

允许提供多个构造函数,服从与其他函数完全一样的重载规则。

另外,可以采用默认参数的方法:

class Date {
  int d, m, y;
public:
  Date(int dd =0, int mm =0, int yy =0);                  //构造函数
  void add_year(int n);                 //加n年
  void add_month(int n);                //加n月
  void add_day(int n);                  //加n天
};

Date today;
                                                                                        
Date::Date(int dd, int mm, int yy) {
  d = dd ? dd : today.d;
  m = mm ? mm : today.m;
  y = yy ? yy : today.y;
}

 

 


 

 

P203  静态成员

上述Date类依靠一个全局变量today。使这个类在其他环境基本上不能用,形成限制。

如果一个变量是类的一部份,但却不是该类的各个对象的一部分,它就被称为是一个static静态成员。

一个static成员只有唯一的一份副本,而不像常规的非static成员那样在每个对象里各有一份副本。

与此类似,一个需要访问类成员,却不需要针对特定对象去调用的函数,被称为一个static成员函数。

 

对静态成员(包括静态数据成员和静态函数成员)的引用不必提到任何对象,但需要给成员的名字加上作为限定词的类名字。。

静态成员,必须在某个地方另行定义。

class Date {
  int d, m, y;
  static Date default_date;
public:
  Date(int dd =0, int mm =0, int yy =0);                  //构造函数
  //...                                                                                 
  static void set_default(int, int, int);
};

Date::Date(int dd, int mm, int yy) {
  d = dd ? dd : default_date.d;
  m = mm ? mm : default_date.m;
  y = yy ? yy : default_date.y;
}

Date Date::default_date(16, 12, 1770);

void Date::set_default(int d, int m, int y) {
  Date::default_date = Date(d, m, y);
}

void f() {
  Date::set_default(4, 5, 1945);
}

 

 

 


 

 

P205  常量成员函数

到目前位置,所定义的Date只提供了一些给定Date的值或者改变其值的函数。

接下来提供一些函数来检查一个Date的值。

class Date {
  int d, m, y;
public:
  int day() const { return d; }
  int month() const { return m; }
  int year() const { return y; }
  //...                                                                                 
};

 

 

注意:在这些函数声明的空参数表后面出现的const,它指明这些函数不会修改Date的状态。

inline int Date::year() const {   //错误:在const函数里企图修改成员值
  return y++;
}

inline int Date::year() const {   //ok
  return y;
}

inline int Date::year() {         //错误:函数不匹配Date中的任何一个,在成员函数类型中缺少const
  return y;
}

 

对于const或者非const对象都可以调用const成员函数,而非const成员函数则只能对非const对象调用:

void f(Date& d, const Date& cd) {
  int i = d.year();   //ok
  d.add_year(1);      //ok

  int j = cd.year();  //ok
  cd.add_year(1);     //错误:不能修改const cd的值
}

 

 


 

 

P205  自引用

状态更新函数add_year()、add_month()和add_day、都被定义为不返回值的函数。对于这样的函数,可以让它们返回一个到被更新对象的引用,以使对于对象的操作可以串接起来。这种技术很有用。。。

 表达式*this引用的就是这个函数的这次调用所针对的那个对象。。

 

 

class Date {
  int d, m, y;
public:
  Date& add_day(int n);
  Date& add_month(int n);
  Date& add_year(int n);
  //...
};

void f(Date& d) {
  d.add_day(1).add_month(1).add_year(1);
}
                                                                                                                                                                                                             
Date& Date::add_year(int n) {
  if(d==29 && m == 2 && !leapyear(y+n)) {
    d = 1;
    m = 3;
  }
  y += n;
  return *this;
}

 

 

  


 

 

 

posted on 2013-06-30 20:25  Ac_coral  阅读(267)  评论(0编辑  收藏  举报

导航