zoukankan      html  css  js  c++  java

  • 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;
    }

      


     

  • 相关阅读:
    python epoll
    解决linux下/etc/rc.local开机器不执行的原因
    xen4.1.2网桥配置
    用户激励设计[转]
    C#4.0的dynamic和var及object关键字辨析
    动态设置和修改Membership/Profile/RoleProvider的ConnectionString数据库连接字符串
    UseCase用例怎么画_UML用例UseCase的几个理解误区
    C#的delegate/event/Action/Func/Predicate关键字
    我为什么鄙视提倡加班的公司
    [转]个人成长之通关路!
  • 原文地址:https://www.cnblogs.com/Accoral/p/3163808.html
Copyright © 2011-2022 走看看