1. 程式人生 > >C++ 類 超細節攻略

C++ 類 超細節攻略

顯式 isbn 常量指針 acc signed char ces const對象 對象的引用

C++坑了我不少的時間,這回把類算是弄得明白一些,在此記錄一下。內容非常繁雜,請做好心理準備。

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

① 編譯器分兩步處理類:

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

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

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

③ .h文件 (註意:是struct)

 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函數

 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 與⑦的類示例友元類

 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 }

如有補充歡迎留言~

C++ 類 超細節攻略