最近在看《C++ primer》,做到了練習7.27的時候,遇到了一些問題,在此記錄,
1 先貼代碼
1.1 .h代碼
- #include <cstdlib>
- #include <cstdio>
- #include <string>
- #include <iostream>
- using namespace std;
- class Screen
- {
- typedef string::size_type pos;
- public:
- Screen() = default;
- Screen(pos high, pos wide, char c) : height(high), width(wide), contents(high * wide, c){};
- inline Screen &set(pos row, pos col, char c);
- // #5
- inline Screen &display(ostream &os);
- // #6
- inline const Screen &display(ostream &os) const;
- inline Screen &move(pos row, pos col);
- private:
- pos height = 0, width = 0;
- pos cursor = 0;
- mutable string contents;
- // #1
- // inline void do_display(ostream &os) const{
- // os << contents;
- // }
- // #3
- inline void do_display(ostream &os /*這里的&不能少*/) const;
- }; // #4, 這里的分號";"不能少
- //typedef string::size_type pos;并不需要重復定義
- inline Screen &Screen::set(pos row, pos col, char c)
- {
- contents[(row - 1) * width + (col - 1)] = c;
- return *this;
- }
- inline Screen &Screen::move(pos row, pos col)
- {
- cursor = row * width + col;
- return *this;
- }
- inline Screen &Screen::display(ostream &os)
- {
- do_display(os);
- return *this;
- }
- inline const Screen &Screen::display(ostream &os) const
- {
- do_display(os);
- return *this;
- }
- // #2
- inline void Screen::do_display(ostream &os) const
- {
- os << contents;
- //return *this;
- }
1.2 .cpp代碼
- #include "exercise_7_27.h"
- using namespace std;
- int main()
- {
- Screen pm1(3, 3, '@');
- const Screen pm2(3, 3, '$');
- pm1.display(cout);
- cout << '\n';
- pm1.set(3, 1, '#').display(cout);
- cout << '\n';
- // #7
- pm2.display(cout);
- cout << '\n';
- }
2 問題與識訓
2.1 類內私有成員可以外部定義
如"#1"和"#2"處的兩段對do_display()的定義,在類內宣告并定義private成員函式是可以的,同樣在類內宣告,隨后在類外定義也是可以的,
2.2 std::ostream os和std::ostream &os引起的錯誤
在"#3"處的代碼,可以看到形參串列中有一個std::ostream &os,這里是指將輸出流的參考傳入了函式,但是第一次寫程式的時候忘記加這個&了,而是變成了輸出流的拷貝來使用,出現了如下的錯誤:
use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&)
2.3 類的定義域后沒加分號
在"#4"處的大括號結尾處,如果程式沒有在此結束,則strut/class{}的后面需要加分號";",不然會報錯,如下:
expected initializer before '&' token
但是回頭審查代碼,這個分號是在第32行沒有加的,卻提醒我35行的Screen &Screen::move(…)的參考符號出現了問題,真是費解,
2.4 類內成員函式關于const修飾引起的多載
可以看到在"#5"和"#6"的地方定義了兩次display()這個函式,主要的區別是對回傳的型別的限定不同,都是回傳函式指標的函式,但是第一個是回傳的非常量型別的(*this),第二個卻是常量型別的,
具體的呼叫多載區別可以看.cpp檔案內的"#7"部分,當在vscode 的IDE下進行撰寫的時候,對于非常量的Screen物件pm1,當你敲下"."的時候,所有在public中定義的成員都是可見的;但是常量的物件pm2只能看到多載的const Screen &Screen::display() const{…},
2.5 前后const的限定作用
需要特別注意的是,平時雖然后面的const并不影響回傳物件的常量屬性,只是影響成員函式對成員的可操作性,但是當回傳的物件型別是函式型別的時候,如果后面加了const限定符,則呼叫該成員函式的時候,this指標指向的物件就是常量,
舉個例子,Screen &Screen::display() {…}和const Screen &Screen::display() const{…}中都呼叫了inline void Screen::do_display(ostream &os) const {…},但是不論是第一個display()還是第二個,當呼叫do_display() const {…}的時候,this指標指向的物件都被隱式地轉化為了常量物件,當參考結束后回傳的this仍然是呼叫之前的this型別,
所以可以推匯出如果只有前面的const,那么在呼叫第二個display()函式的時候,回傳的this指標是非常量的,這和宣告的回傳型別不符,但是只有后面的const的時候,兩個display()函式從形參到回傳型別都是一樣的,就出現了多載的二義性問題,編譯同樣無法通過,
2021.4.18 13:31
于寧波大學園區圖書館二樓窗邊
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/279165.html
標籤:C++
