C++坑了我很多的時間,這回把類算是弄得明白一些,在此記錄一下。內容很是繁雜,請作好心理準備。函數
我會以代碼的形式來表達,而且附上一些解釋。this
① 編譯器分兩步處理類:spa
② C++ 中class與struct的區別?指針
③ .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