《C++ Primer》第7章 7.4节习题答案

《C++ Primer》第7章 类

7.4节 类的作用域

练习7.33:如果我们给Screen添加一个如下所示的size成员将会发生什么情况?发果出现了问题,请尝试修改它。

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


【出题思路】
考查类的作用域。
【解答】
如果添加如题目所示的size函数将会出现编译错误。因为该函数的返回类型pos本身定义在Screen类的内部,所以在类的外部无法直接使用pos。要想使用pos,需要在它的前面加上作用域Screen::。修改后的程序是:
 

Screen::pos Screen::size() const
{
        return height * width;
}
#include <iostream>
#include <string>

using namespace std;

class Window_mgr
{
public:
    void clear();
};

class Screen
{
    friend void Window_mgr::clear();        //不定义友元,编译通不过
public:
    typedef std::string::size_type pos;
    Screen() = default;
    Screen(unsigned ht, unsigned wd, char c)
        :height(ht), width(wd), contents(ht * wd, c)
    {

    }

    pos size() const;

private:
    unsigned height = 0, width = 0;
    unsigned cursor = 0;
    string contents;

    pos ht = 24, wd = 80;
};

Screen::pos Screen::size() const        //pos前面要加作用域
{
    return height * width;
}

void Window_mgr::clear()
{
    Screen myScreen(10, 20, 'X');
    cout << "请理之前myScreen的内容是:" << endl;
    cout << myScreen.contents << endl;
    cout << "size=======" << myScreen.size() << endl;
    myScreen.contents = "";
    cout << "请理之后myScreen的内容是:" << endl;
    cout << myScreen.contents << endl;
}


int main()
{
    Window_mgr w;
    w.clear();

    return 0;
}

运行结果:

 

练习7.34:如果我们把第256页Screen类的pos的typedef放在类的最后一行会发生什么情况?
【出题思路】
本题考查用于类成员声明的名字查找。
【本题解答】
这样做会导致编译出错,因为对pos的使用出现在它的声明之前,此时编译器并不知道pos到底是什么含义。
注意:类的编译分为两部先编译类的成员,再编译函数体。

练习35:解释下面代码的含义,说明期中的和分别使用了哪个定义,如果代码存在错误,尝试修改它。
typedef string Type;
Type initVal();

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

Type Exercise::setVal(Type parm) {
        val = parm + initVal();
        return val;
}
【出题思路】
理解名字查找与类的作用域的关系,包括用于类成员声明的名字查找和成员定义中的名字查找。
【解答】
代码的含义及Type和initVal的使用请参考注释。
typedef string Type;                    //声明类型别名Type表示string
Type initVal();                         //声明函数initVal,返回类型是Type


class Exercise                          //定义一个新类Exercise
{
public:
    typedef double Type;                //在内层作用域重新声明类型别名Type表示double
    Type setVal(Type);                  //声明函灵敏setVal,参数和返回值的类型都是Type
    Type initVal();                     //在内层作用域重新声明函数initVal,返回类型是Type
    
private:
    int val;                            //声明私有数据成员val
};
//定义函数setVal,此时的Type显然是外层作用域string
Type Exercise::setVal(Type parm)
{
    val = parm + initVal();             //此处使用的是类内的initVal函数
    return val;                         //返回的是double
}
//改成
Exercise::Type Exercise::setVal(Type parm)
{
    val = parm + initVal();             //此处使用的是类内的initVal函数
    return val;                         //返回的是double
}

其中,在Exercise类的内部,函数setVal和initVal用到的Type都是Exercise内部声明的类型别名,对应的实际类型是double。在Exercise类的外部,定义Exercise::setVal函数时形参类型Type用的是Exercise内部定义的别名,对应double;返回类型Type用的是全局作用域的别名,对应string。使用的initVal函数是Exercise类内定义的版本。编译上述程序时在setVal的定义处发生错误,此处定义的函数形参类型是double、返回值类型是string,而类内声明的同名函数形参类型是double、返回值类型也是double,二者无法匹配。修改的措施是在定义setVal函数时使用作用域运算符强制指定函数的返回值类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值