C++ 類 超細節攻略

C++坑了我很多的時間,這回把類算是弄得明白一些,在此記錄一下。內容很是繁雜,請作好心理準備。函數

我會以代碼的形式來表達,而且附上一些解釋。this

① 編譯器分兩步處理類:spa

  • 編譯成員的聲明
  • 直到類所有可見後才編譯成員函數體

② C++ 中class與struct的區別?指針

  • C++中惟一區別就是默認的訪問權限,struct是public,class是private
  • C#中區別很大,詳情百度

③ .h文件 (注意:是struct)code

 1 struct Sales_data
 2 {
 3     // 定義友元函數讓其能夠訪問類的非公有成員
 4     friend Sales_data add(const Sales_data &, const Sales_data &);
 5 
 6 public:
 7     // Sales_data() = default;
 8     // 構造函數,不能聲明const
 9     // 等同於編譯器自動合成的構造函數
10     // 在(= default)在類的內部,則默認構造函數是內聯的,如在類的外部,則該成員默認不是內聯的
11 
12     Sales_data() : Sales_data("", 0, 0) {}
13     // 委託構造函數:使用它所屬的類的其餘構造函數執行本身的初始化過程
14 
15     /* explicit 抑制構造函數的隱式轉換,只容許出現的類內*/ Sales_data(const string &s) : bookNo(s) {}
16     Sales_data(const string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {}
17 
18     string isbn() const {return bookNo;}
19     // 等價於
20     // string isbn(const Sales_data *const this//隱式//) {return this->bookNo;}
21     // 意思就是this是一個指向常量的常量指針。不能修改this中的內容。
22 
23     Sales_data& combine (const Sales_data&);
24 
25 
26 private:
27     double avg_price() const;
28     string bookNo;
29     unsigned units_sold = 0;
30     double revenue = 0.0;
31 };

④ .cpp文件對象

 1 Sales_data& Sales_data::combine(const Sales_data &rhs)
 2 {
 3     units_sold += this->units_sold;
 4     revenue += rhs.revenue;
 5     return *this; // 返回指針引用  6 }
 7 
 8 double Sales_data::avg_price() const
 9 {
10     if (units_sold)
11         return revenue / units_sold;
12     else
13         return 0;
14 }
15 
16 Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
17 {
18     Sales_data sum = lhs;
19     sum.combine(rhs);
20     return sum;
21 }

⑤ main函數blog

 1 int main()
 2 {
 3     Sales_data total;
 4     total.isbn();
 5     // 等價於
 6     // total.isbn(&total);
 7     // 調用時候傳入了total對象的地址
 8 
 9     const Sales_data sales_data;
10     // 直到構造函數完成初始化過程,對象才能真正取得其「常量」屬性
11     // 構造函數在const對象的構造過程當中能夠向其寫值
12 
13     total.combine(sales_data).isbn();
14     // 非引用傳參調用拷貝構造(此函數是引用參數,則沒有拷貝構造)
15     // 返回一個類對象調用拷貝構造
16 
17     total = sales_data;
18     // 賦值操做
19 
20     Sales_data obj();  // 聲明瞭一個函數
21     Sales_data obj2;   // 聲明瞭一個對象
22 
23     Sales_data item;
24     string null_book = "9-999-99999-9";
25     item.combine(null_book); // 將null-book隱式轉換成Sales_data對象
26     //item.combine("9-999-99999-9"); // 錯誤,只容許一步轉換,不能將字符轉換成string再轉換成對象
27 
28     // this 是一個常量指針
29     return 0;
30 }

⑥ class Screen 與⑦的類示例友元類ci

 1 class Screen
 2 {
 3 public:
 4     typedef std::string::size_type pos;
 5     // 等同於
 6     // using pos = std::string::size_type;
 7     // 必須先定義後使用
 8 
 9     friend class Window_mgr;
10     // Window_mgr的成員能夠訪問Screen類的私有成員
11 
12     // friend void Window_mgr::clear(ScreenIndex);
13     // 讓函數做爲友元
14 
15     Screen() = default;
16     Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) {}
17 
18     char get() const // 隱式內聯
19     {
20         return contents[cursor];
21     }
22 
23     inline char get(pos ht, pos wd) const; // 顯式內聯
24 
25     Screen &move(pos r, pos c); // 能夠在類的外部聲明時定義成內聯函數
26 
27     Screen &set(char);
28 
29     Screen &set(pos, pos, char);
30 
31     const Screen &display() const;
32 
33     void dummy_fcn(pos height)
34     {
35         cursor = width * height; // 用的是參數height
36         cursor = width * this->height; // 用的是成員height
37         // cursor = width * ::height; // 用的是全局的height
38     }
39 
40 private:
41     pos cursor = 0;
42     pos height = 0, width = 0;
43     std::string contents;
44     mutable size_t access_ctr = 0; // mutable(可變數據成員),在const成員函數中也能夠改變值
45 };
46 
47 char Screen::get(pos ht, pos wd) const
48 {
49     pos row = ht * width;
50     ++access_ctr; // 正確
51     // ++cursor; 錯誤
52     return contents[row + wd];
53 }
54 
55 inline Screen &Screen::move(pos r, pos c) // 聲明的時候聲明inline函數
56 {
57     pos row = r * width;
58     cursor = row + c;
59     return *this;
60 }
61 
62 inline Screen &Screen::set(char c)
63 {
64     contents[cursor] = c;
65     return *this;
66     // 返回對象的引用,說明返回的是對象自己,而不是對象的拷貝
67     // 若是返回類型爲Screen,則返回的是對象的拷貝
68 }
69 
70 inline Screen &Screen::set(pos r, pos col, char ch)
71 {
72     contents[r * width + col] = ch;
73     return *this;
74 }
75 
76 inline const Screen &Screen::display() const
77 {
78     return *this; // const成員函數返回其指針,則爲常量指針
79 }

⑦ class Window_mgr作用域

 1 class Window_mgr
 2 {
 3 public:
 4     using ScreenIndex = std::vector<Screen>::size_type;
 5 
 6     void Clear(ScreenIndex);
 7 
 8     ScreenIndex addScreen(const Screen&);
 9 
10 private:
11     std::vector<Screen> screens{ Screen(24, 80, ' ') };
12     // 類內初始值,必須以符號=或{}表示
13 };
14 
15 void Window_mgr::Clear(ScreenIndex index) // void 爲做用域以外,從Window_mgr開始爲做用域內
16 {
17     Screen &s = screens[index];
18     s.contents = std::string(s.height * s.width, ' ');
19     // 因Window_mgr是Screen的友元類,因此能夠訪問Screen的私有成員height、width和contents
20     // 注:友元關係不存在傳遞性,若是Window_mgr有友元類,其友元類沒有訪問Screen的權利
21 }
22 
23 Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen &s) // 返回類型在類做用域中定義,則必須用類名
24 {
25     screens.push_back(s);
26     return screens.size() - 1;
27 }

若有補充歡迎留言~get

相關文章
相關標籤/搜索