[2018年4月22号]C++ primer 课后练习 第七章 类

7.23,7.24
class Screen {
public:
    typedef string::size_type pos;

    Screen() = default;
    Screen(pos wightVal, pos heightVal):wight(wightVal), height(heightVal), contents(wightVal*heightVal, ' ') {
        cout << contents << " " << wight << " " << height << endl;
    }
    Screen(pos wightVal, pos heightVal, char contents) :wight(wightVal), height(heightVal), contents(wightVal*heightVal,contents){
        cout << contents << " " << wight << " " << height << endl;
    }

private:
    pos cursor = 0;
    pos wight= 0, height = 0;
    string contents;
};

7.25,对该题目的答案保有疑问,通过网上查询答案为大多数为不能,但个人觉得是可以的,并做了以下检验:


成功输出拷贝后的数据,(将两个参数的构造函数改为默认插入字符b而不是空格来方便查看结果)

翻阅书本在P239上写明是关于内存操作的拷贝和赋值才会有合成版本的问题,在P240页第一段也写明了"如果类包含vector或者string成员,则其拷贝,赋值和销毁的合成版本能够正常工作"

7.26:

在类外需要加上inline关键字,在类内定义的话将默认是内联函数

7.27

class Screen {
public:
    typedef string::size_type pos;

    Screen() = default;
    Screen(pos wightVal, pos heightVal):wight(wightVal), height(heightVal), contents(wightVal*heightVal, ' ') {
    }
    Screen(pos wightVal, pos heightVal, char contents) :wight(wightVal), height(heightVal), contents(wightVal*heightVal,contents){
    }
    Screen& set(char);
    Screen& move(pos r, pos col);
    Screen& display(ostream& os);
    int getWight()const { return wight; }
    string getContents()const { return contents; }
    int getHeight()const { return height; }
private:
    pos cursor = 0;
    pos wight= 0, height = 0;
    string contents;
    void do_displayer(ostream& os){
        os << contents;
    }
};

inline
Screen& Screen::set(char c){
    contents[cursor] = c;
    return *this;
}
inline
Screen& Screen::move(pos r, pos col){
    cursor = wight * r +col;
    return *this;
}
inline
Screen& Screen::display(ostream& os){
    do_displayer(os);
    return *this;
}


int main() {
    Screen myScreen(5, 5, 'x');
    myScreen.move(4,0).set('#').display(cout);
    cout<<'\n';
    myScreen.display(cout);
    cout<<'\n';
    for (;;);
    return 0;
}

7.28

第一次改变就不是我们声明的myScreen,而每次操作函数后都会生成一个新的临时变量,我们只是对临时变量进行操作

第二次display输出的就是原来我们声明初未进行任何修改的的myScreen

7.29


7.30

优点,在新手阶段,对函数调用形参还是成员函数方便理解

熟悉之后,再使用this可能会导致程序的简洁程度下降


7.31:????

class Y {
    X x;

};
class X {
    Y* y;
};
7.32
using namespace std;
class Screen {
public:
    typedef string::size_type pos;
    friend class Window_mgr;
    Screen() = default;
    Screen(pos wightVal, pos heightVal):wight(wightVal), height(heightVal), contents(wightVal*heightVal, ' ') {
    }
    Screen(pos wightVal, pos heightVal, char contents) :wight(wightVal), height(heightVal), contents(wightVal*heightVal,contents){
    }
    Screen& set(char);
    Screen& move(pos r, pos col);
    Screen& display(ostream& os);
    int getWight()const { return wight; }
    string& getContents(){ return contents; }
    int getHeight()const { return height; }
    pos size()const;
private:
    pos cursor = 0;
    pos wight= 0, height = 0;
    string contents;
    void do_displayer(ostream& os){
        os << contents;
    }
};


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


class Window_mgr {
public:
    typedef  string::size_type ScreenIndex ;
    void clear(ScreenIndex index);
private:
    vector<Screen> screens{ Screen(24, 80, ' ') };
};


void Window_mgr::clear(ScreenIndex index){
    Screen & s = screens[index];
    s.getContents() = string(s.getWight()*s.getHeight(), ' ');
}


inline
Screen& Screen::set(char c){
    contents[cursor] = c;
    return *this;
}
inline
Screen& Screen::move(pos r, pos col){
    cursor = wight * r +col;
    return *this;
}
inline
Screen& Screen::display(ostream& os){
    do_displayer(os);
    return *this;
}
int main() {
    for (;;);
    return 0;
}

7.33:

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

7.34:

名字查找指包括成员函数出现之前的部分,所以,编译器会报错

7.35

存在作用域判断错误:

修改后如下:

typedef string Type;
Type initVal(){}
class Exercise {
public:
    typedef double Type;
    Type setVal(Type);
    Type initVal(){ val = 1; return val;}
private:
    int val;
};

Exercise::Type Exercise::setVal(Exercise::Type param){
    val = param + Exercise::initVal();
    return val;
}

7.36:

根据编译器不同,可能有不同结果,所以不要用成员变量去列表初始化另一个成员变量

作如下更改:

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

7.37:first_item使用了 Sales_data(std::istream &is)根据输入流初始化

剩余都是 Sales_data(std::string s = "") 初始化,next 默认值为"", last默认值为9-999-99999-9

7.38

struct X {
    X(istream& is = cin){is>>s;}
    string s;
};

7.39

当然不合法,两个构造函数都会匹配构造,产生二义性


7.40:略

7.41:委托构造函数如被委托构造函数体内有代码,则先执行这些代码

具体Sales_data 略

7.42:同上,略

7.43

 
 
struct NoDefault {
    NoDefault(int i):intValue(i){};
    int intValue;
};
struct C { C(){}; NoDefault no = NoDefault(5);};



struct C {
    C(NoDefault n = 5): no(n){};
    NoDefault no ;
};

7.44:

不合法,没有默认构造参数

7.45

合法,虽然NoDefault没有默认构造函数,但是我们给C配置了默认构造函数

7.46

a.不正确,如果没有构造函数,系统会自动生成一个合成构造函数

b.不正确,默认构造函数可以有形参,只需带上默认实参即可

c.不正确,会导致后续使用时不便如作他类成员变量

d.正确

7.47:

优点:都不能隐式初始化

缺点:必须显示初始化

7.48

如果不是explicit,全可通过编译

如是,也全可通过编译


7.49

a,传入一个临时变量Sales_data

b.传入Sales_data引用

c.传入Sales_data常量引用,不能修改传入的Sales_data变量的值

7.50

可加可不加

7.51

可以防止意义不明

x(vector<int>)

如果不是explicit

x(10)就产生歧义

7.52:

不能携带默认初始值

修改后如下

struct Sales_data {
    string bookNo;
    unsigned units_sold;
    double revenue;
};

7.53

class Debug {
public:
    constexpr Debug(bool b = true) :hw(b), io(b), other(b) {}
    constexpr Debug(bool h, bool i, bool o) : hw(h), io(i), other(o) {}
    constexpr bool any(){return hw||io||other;}
    void set_id(bool b)    { hw = b; }
    void set_hw(bool b)    { io = b; }
    void set_other(bool b) { other = b; }
private:
    bool hw;
    bool io;
    bool other;
};

7.54

不该吧,成员变量都不是const或者constexpr的

7.55

不是,并不是常量成员


猜你喜欢

转载自blog.csdn.net/qq_22478401/article/details/80038188