C++_notes3

p10. 类模板,函数模板,static

  • static and this
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Account {
    public:
    static double m_rate;
    static void set_rate (const double& x) { m_rate = x; }
    };
    double Account::m_rate = 8.0; //definition: 分配内存

    int main () {
    Account::set_rate(5.0);

    Account a;
    a.set_rate(7.0);
    }
    • 成员函数有一个默认的参数 this*, 不用写到参数里
    • static数据是可以共享的(eg. 银行的利率),static成员函数没有this*, 只能处理static数据
    • 调用static函数的方式:
      • 通过object来调用 –> 没有this*
      • 通过class name来调用 –> 可能还没有创建对象
  • class template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    template <typename T>
    class Complex
    {
    public:
    complex (T r = 0, T i = 0)
    : re (r), im (i)
    { }
    complex& operator += (const complex&);
    T real () const { return re; }
    T imag () const { return im; }
    private:
    T re, im;
    };
    {
    complex<double> c1(1.2, 1.5);
    complex<int> c2(2, 3);
    ...
    }
  • function template: 对于不同的class,可以用一个函数

    • 可以不指定类名,编译器会对function template进行参数推导(argument deduction)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      template <class T>
      inline
      const T& mini(const T& a, const T& b)
      {
      return b < a ? b : a;
      }
      class stone
      {
      public:
      stone (int h, int we)
      : _h(h), _weight(we)
      { }
      bool operator < (cosnt stone& rhs) const
      {
      return _weight < rhs._weight;
      }
      private:
      int _h, _weight;
      };
      stone r1(2, 3), r2(2, 3);
      Stone r3 = mini(r1, r2);
  • namespace

    • using directive –> using namespace std;
    • using declaration –> using std::cout;

p11. 组合与继承

  • 组合 (composition) -> has-a

    • container空心菱形指向component
    • queue <>—deque
    • e.g. queue has deque, deque inside queue (queue的所有功能都是靠deque来实现) –> Adapter (减少功能)
      1
      2
      3
      4
      5
      template <class T>
      class queue {
      protected:
      deque<T> c;
      };
    • 组合下的构造和析构
      • Container(queue) --> Component(deque)
      • 构造由内而外: 先调用Component的default构造函数, 再调用Container
      • 析构由外而内: 先执行自己(container), 再调用Component
      • 生命是一起出现 一起消失
  • 委托 (Delegation) -> composition by reference

    • 实心菱形指向component
    • String <>—StringRep
    • avatar
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      // file String.hpp
      class StringRep;
      class String {
      public:
      String();
      String(const char* s);
      String(const String& s);
      String &operator=(const String& s);
      ~String();
      }
      private:
      StringRep* rep; // pimpl: point to implementation
      };
      // file String.cpp
      #include "String.hpp"
      namespace {
      class StringRep {
      friend class String;
      StringRep(const char* s);
      ~StringRep();
      int count; // count the number of refernece
      char* rep;
      };
      }
    • 编译防火墙,左边只需编译一次,只改变指向的那个类
    • 生命不一定是同时出现的
    • 多个指针指向同一个字符串,count用来记录reference的数目,读不影响,写入时需要单独复制一份给每个指针
  • 继承(Inheritance) –> is-a

    • 子类(derived class)指向父类(base class),空心三角
    • 子类完全继承父类的数据
    • 构造与析构与组合相同
    • base class的dtor必须是virtual,否则会出现undefined behavior
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      struct _List_node_base
      {
      _List_node_base* _M_next;
      _List_node_base* _M_prev;
      };
      template<typename _Tp>
      struct _List_node
      : public _List_node_base
      {
      _tp _M_data;
      };

p11. 虚函数与多态

  • virtual:

    • non-virtual: 不希望derived class重新定义(override)
    • virtual: 希望derived class重新定义,自己已经有默认定义
    • pure virtual: derived class一定要定义, 没有默认定义
      1
      2
      3
      4
      5
      6
      7
      8
      class Shape {
      public:
      virtual void draw () const = 0; // pure virtual
      virtual void error (const std::string& msg); // virtual, 子类可以定义更详细的error
      int objectID () const; // non-virtual
      };
      class Rectangle: public Shape {...};
      class Ellipse: public Shape {...};
    • 实际应用: (template method) 读取文件时, 除了文件内容不一样,其他的步骤都是一样的,所以其他的步骤都可以提前写好,子类来实现文件内容的读取
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #include <iostream>
    using namespace std;

    class CDocument
    {
    public:
    void OnFileOpen()
    {
    // 每个cout代表一个实际动作 (function)
    cout << "dialog..." << endl;
    cout << "check file status..." << endl;
    cout << "open file ..." << endl;
    Serialize();
    cout << "close file..." << endl;
    cout << "update all views..." << endl;
    }
    virtual void Serialize() { };
    };

    class CMyDoc : public CDocumnet
    {
    public:
    virtual void Serialize()
    {
    cout << "CMyDoc::Serialize() << endl;"
    }
    };

    int main ()
    {
    CMyDoc myDoc;
    myDoc.OnFileOpen(); // 先调用CDocument::OnFileOpen(&myDoc), 在Serialize时调用myDoc的Serialize()
    }
0%