Chapter 12. Classes

  • 类的定义

    • 访问标号的出现次数通常没有限制,就是说你可以有几个private几个public
    • 类的设计者是为类的用户实现类,这个用户是程序员。好的类设计者会定义直观易用的类接口
    • 一旦改变了类文件,所有引用了类的头文件的源代码都要重新编译。
    • 可以定义类的局部别名,比如typedef std::string::size_type index;
    • 可以在类内部定义inline函数,实现在外部。
    • 类可以前置声明,这时候使用就受限,只能是作为指针或者引用出现。所以当在类的内部定义一个该类类型的成员的时候,要注意只能是指向该类的指针或引用。
    • 类定义的花括号后面有个分号。。因为后面可以接一个对象表。
  • 隐含的this指针

    • 每个成员函数都有一个隐藏的指向当前对象的this形参。

    • 可以用*this来返回当前对象的引用。从const成员函数返回的就是const引用。

    • 基于返回类型是否是const可以重载函数

    • mutable声明的变量,在const成员函数里也可以改变它的值。

    • 写在外面的成员函数的返回类型是在类的作用域外定义的,所以要加限定。比如

      class Screen {
      public:
      typedef std::string::size_type index;
      index get_cursor() const;
      

    };
    inline Screen::index Screen::get_cursor() const
    {
    return cursor;
    }
    ```

    • 碰到一个变量名,查找名字的时候,先在这个block里找,找不到再到定义的类里找,然后是函数前面找。假如几个作用域里有相同的名字,就会发生屏蔽。
  • 构造函数

    • 构造函数可以看作两个阶段,一个是初始化阶段,一个是构造函数的函数体内语句执行的阶段。所以假如没有在初始化列表里显式初始化,对类类型的成员来说还是会在初始化阶段调用它的默认初始化函数的。

    • 注意:对于在构造函数体内赋值不起作用的成员变量,就必须在构造函数初始化列表里初始化。比如没有默认构造函数的类类型的成员,const或引用类型的成员。看这个例子

      class ConstRef {
      

    public:
    ConstRef(int ii);
    private:
    int i;
    const int ci;
    int &ri;
    };
    // no explicit constructor initializer: error ri is uninitialized
    ConstRef::ConstRef(int ii)
    { // assignments:
    i = ii; // ok
    ci = ii; // error: cannot assign to a const
    ri = i; // assigns to ri which was not bound to an object
    }

      // ok: explicitly initialize reference and const members
      ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }
      ```
    
    • 用初始化列表初始化的顺序是按照成员变量在类里定义的顺序来的。
    • 初始化式可以是任意复杂的表达式
    • 隐式类型转换,就像之前的内置类型存在隐式转换一样,类也可以隐式转换,具体情况是一个函数需要一个类作参数的时候,传进去的假如不是类的对象,而是这个类的构造函数参数,那么就会发生隐式转换。
    • explict关键字可以防止自动隐式转换发生
    • 结构体也要初始化,按照它们在类里的定义顺序来。
  • 友员

    • friend机制允许一个类将对其非公有成员的访问权授予指定的函数或类。
    • friend只能在类内部声明,声明的对象可以是别的类,别的类的成员函数,普通函数。
  • static类成员

    • static成员变量,被所有该类的对象共享。在类里声明之后,必须在类外定义一次,因为static类型的变量不会像普通类成员一样在类初始化的时候初始化。最好的方法是在类的implement文件里定义一下,需要类的限定符,不管是private还是public都可以A::svar这样去定义。
    • static成员函数只需要在类里面定义的时候写出static,在类外部可以参略关键字。
    • const static可以在类里面初始化给定初始值,但是即便这样,在类外面还是需要再定义一次。但这时候就可以不必指定初始值了。
    • static声明的变量,可以是这个类的对象。只有它允许,而普通声明的变量只能是类的指针或者引用