《C++ Primer》5th 課後練習 第七章 類 31~40

練習7.31 定義一對類X 和Y,其中X 包含一個指向 Y 的指針,而Y 包含一個類型爲 X 的對象。

class Y;
class X
{
private:
	Y* p = nullptr;
};
class Y
{
private:
	X p;
};

練習7.32 定義你自己的Screen 和 Window_mgr,其中clear是Window_mgr的成員,是Screen的友元。

//Screen.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Screen;
class Window_mgr {
public:
	using ScreenIndex = std::vector<Screen>::size_type;
	void clear(ScreenIndex i);
private:
	std::vector<Screen> screens;
};
class Screen {
	//friend class Window_mgr;
	friend void Window_mgr::clear(std::vector<Screen>::size_type i);
public:
	using pos = std::string::size_type;
	Screen() = default;
	Screen(const pos h, const pos w) :
		height(h), width(w), contents(h*w, ' ') {}
	Screen(const pos h, const pos w, const char c):
		height(h), width(w), contents(h*w, c) {}
	char get() const {return contents[cursor];}
	char get(pos r, pos c) const { return contents[width*r+c]; }
	Screen &move(pos r, pos c) { cursor = r * width + c; return *this; }
	Screen &set(const char c) { contents[cursor] = c; return *this; }
	Screen &set(pos r, pos col, const char ch) { contents[r*width + col] = ch; return *this; }

	Screen &display(ostream &os) {	do_display(os);	return *this;	}
	const Screen &display(ostream &os) const { do_display(os);	return *this; }
private:
	void do_display(ostream &os)const { os << contents; }
	pos cursor = 0;
	pos height = 0, width = 0;
	string contents;
};

void Window_mgr::clear(ScreenIndex i) {
	Screen &s = screens[i];
	s.contents = string(s.height * s.width, ' ');
}

PS:感覺這種寫法十分不友好,很容易導致邏輯混亂,如果不熟悉C++的程序員維護這段代碼,非常有可能導致錯誤。

練習7.33 如果我們給Screen 添加一個如下所示的size成員將發生什麼情況?如果出現了問題,請嘗試修改它。

pos Screen::size() const
{
	return height * width;
}

編譯器會報錯,因爲找不到pos的聲明。應該改爲:

Screen::pos Screen::size() const
{
	return height * width;
}

練習7.34 如果我們把第256頁Screen類的postypedef放在類的最後一行會發生什麼情況?

類中所有是用了pos的地方都會報錯:未定義的標識符pos

類型名的定義通常出現在類的開始處,這樣就能確保所有使用該類型的成員都出現在類名的定義之後。

練習7.35 解釋下面代碼的含義,說明其中的TypeinitVal分別使用了哪個定義。如果代碼存在錯誤,嘗試修改它。

練習7.36 下面的初始值是錯誤的,請找出問題所在並嘗試修改它。

struct X {
	X (int i, int j): base(i), rem(base % j) {}
	int rem, base;
};

應改爲:

struct X{
	X(int i, int j): base(i), rem(base%j){}
	int base, rem;
}

練習7.37 使用本節提供的Sales_data類,確定初始化下面的變量時分別使用了哪個構造函數,然後羅列出每個對象所有的數據成員的值。

Sales_data first_item(cin); // 使用 Sales_data(std::istream &is) ; 各成員值從輸入流中讀取
int main() {
	Sales_data next; // 使用默認構造函數  bookNo = "", cnt = 0, revenue = 0.0

	// 使用 Sales_data(std::string s = "");bookNo = "9-999-99999-9", cnt = 0, revenue = 0.0
	Sales_data last("9-999-99999-9"); 
}

練習7.38 有些情況下我們希望提供cin作爲接受istream& 參數的構造函數的默認實參,請聲明這樣的構造函數。

Sales_data(std::istream & = std::cin);

練習7.39 如果接受string 的構造函數和接受 istream& 的構造函數都使用默認實參,這種行爲合法嗎?如果不,爲什麼?

不合法,會造成二義性調用的錯誤。

練習7.40 從下面的抽象概念中選擇一個(或者你自己指定一個),思考這樣的類需要哪些數據成員,提供一組合理的構造函數並闡明這樣做的原因。

(a) Book (b) Data (c) Employee
(d) Vehicle (e) Object (f) Tree

//Employee.h
#include<string>
class Employee
{
public:
	Employee(const std::string &s, int sly, int dpt, int wy = 0) : emNum(s), salary(sly), department(dpt), workYear(wy) {};//傳入全部參數進行構造
	Employee(const Employee &oth) { *this = oth; }//拷貝構造
	Employee() = default;//默認構造一個空的對象
	~Employee();
private:
	std::string emNum = "";
	int salary = 0;
	int department = 0;
	int workYear = 0;
};
Employee::~Employee()
{

}
發佈了290 篇原創文章 · 獲贊 23 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章