C++ primer plus课后练习题

第十五章:友元、异常和其他

        一、复习题

        1. a. 友元声明应为: friend class clasp

            b. 应该在cuff类前声明muff类

            c. 应该在muff类前声明cuff类。其次,需要muff的前向声明。

        2. 不可以。为使类A拥有一个本身为类B的成员函数的友元,B的声明必须位于 A 的声明之前。一个前向声明是不够的,因为这种声明可以告诉A:B是一个类;但它不能指出类成员的名称。同样,如果B拥有一个本身是A 的成员函数的友元,则A 的这个声明必须位于B的声明之前。这两个要求是互斥的。

        3. 嵌套类被定义为私有成员,意味着在ribs类外无法创建嵌套类的对象。仅能通过ribs类的构造函数创建该嵌套类的一个对象。

        4. return会依次回调先前调用该函数的函数,但throw会跳转到相应的含有try块的调用函数中进行处理。

        5. catch块的顺序应该与继承层次相反,即基类在下,派生类在上。

        6. 第一个实例中,可以调用superb中的say方法以及superb派生类magnificent中的say方法。在第二个实例中,仅能调用superb中的say方法。

        7. static_cast运算符能在类层次中进行向上或向下的转换,但dynamic_cast运算符仅能进行向上的转换。static_cast还允许枚举类型和整型之间以及数值类型之间的转换。

        二、编程练习

        1. 

#ifndef C_PRIMER_CHAPTER15_TV_H
#define C_PRIMER_CHAPTER15_TV_H

class Remote;

class Tv
{
private:
    int state;
    int volume;
    int maxChannel;
    int channel;
    int input;
public:
    friend class Remote;
    enum {Off,On};
    enum {MinVal,MaxVal = 20};
    enum {TV,DVD};

    Tv(int s = Off, int mc = 125):state(s),volume(5),
    maxChannel(mc),channel(2),input(TV){}
    void onOff() {state = state == Off ? On : Off;}
    bool isOn() {return state;}
    bool volUp();
    bool volDown();
    void chanUp();
    void chanDown();
    void set_input() {input = input == TV ? DVD : TV;}
    void settings() const;
    void swicthRemote(Remote& r);
};

class Remote
{
private:
    int mode;
    int r_state;
public:
    friend class Tv;
    enum {Normal,Interactive};
    Remote(int m = Tv::TV,int s = Normal) : mode(m),r_state(s){}
    void onOff(Tv& t) {t.onOff();}
    void volUp(Tv& t) {t.volUp();}
    void volDown(Tv& t) {t.volDown();}
    void chanUp(Tv& t) {t.chanUp();}
    void chanDown(Tv& t) {t.chanDown();}
    void set_chan(Tv& t,int c){t.channel = c;}
    void set_input(Tv& t) {t.set_input();}
    void settings() const;
};

#endif //C_PRIMER_CHAPTER15_TV_H
#include "Tv.h"
#include <iostream>

bool Tv::volUp()
{
    if(volume < MaxVal)
    {
        volume++;
        return true;
    }
    return false;
}

bool Tv::volDown()
{
    if(volume <= MinVal)
        return false;
    volume--;
    return true;
}

void Tv::chanUp()
{
    if(channel == maxChannel)
        channel = 0;
    else
        channel++;
}

void Tv::chanDown()
{
    if(channel == 0)
        channel = maxChannel;
    else
        channel--;
}

void Tv::settings() const
{
    using std::cout,std::endl;
    if(state == On)
    {
        cout << "Tv is On." << endl;
        cout << "Volume: " << volume << endl;
        cout << "Channel: " << channel << endl;
        cout << "Input: " << (input ? "DVD" : "Tv") << endl;
    }
    else
    {
        cout << "Tv is Off." << endl;
    }
}

void Tv::swicthRemote(Remote& r)
{
    if(state == On)
    {
        r.r_state = r.r_state == Remote::Normal ? Remote::Interactive : Remote::Normal;
    }
    else
    {
        std::cout << "Tv is Off." << std::endl;
    }
}

void Remote::settings() const
{
    using std::cout,std::endl;
    cout << "Mode: " << (mode ? "DVD" : "TV") << endl;
    cout << "State: " << (r_state ? "Interactive" : "Normal") << endl;
}
#include "tv.h"

int main() {
    Tv t;
    t.settings();

    Remote r;
    r.settings();

    r.onOff(t);
    t.settings();

    r.volDown(t);
    t.settings();

    t.swicthRemote(r);
    r.settings();

    return 0;
}

        2. 

#include <iostream>
#include <stdexcept>
#include <cmath>

class bad_hmean : public std::logic_error
{
public:
    bad_hmean(const std::string& what_arg = "Invalid for hmean") : std::logic_error(what_arg){}
};

class bad_gmean : public std::logic_error
{
public:
    bad_gmean(const std::string& what_arg = "Invalid for gmean") : std::logic_error(what_arg){}
};

double hmean(double , double );
double gmean(double , double );

int main()
{
    double x,y;
    std::cout << "Enter two numbers: ";
    while(std::cin >> x >> y) {
        try
        {
            std::cout << hmean(x,y) << '\n';
            std::cout << gmean(x,y) << '\n';
            std::cout << "Enter two numbers: ";
        }
        catch (std::exception& e)
        {
            std::cout << e.what();
            std::cout << "\nEnter two numbers: ";
        }
    }

    return 0;
}

double hmean(double x, double y)
{
    if(x == -y)
        throw bad_hmean();
    return 2.0 * x * y / (x + y);
}

double gmean(double x, double y)
{
    if(x < 0 || y < 0)
        throw bad_gmean();
    return sqrt(x * y);
}

        3. 

#include <iostream>
#include <stdexcept>
#include <cmath>

class bad : public std::logic_error
{
private:
    double m_x;
    double m_y;
public:
    bad(double x, double y, const std::string& what_arg = "Invalid arguments\n") : m_x(x),m_y(y),std::logic_error(what_arg){}
    void reports()
    {
        if(m_x == -m_y)
            std::cout << "Error in hmean with x = " << m_x << " and y = " << m_y << std::endl;
        else
            std::cout << "Error in gmean with x = " << m_x << " and y = " << m_y << std::endl;
    }
};

double hmean(double , double );
double gmean(double , double );

int main()
{
    double x,y;
    std::cout << "Enter two numbers: ";
    while(std::cin >> x >> y) {
        try
        {
            std::cout << hmean(x,y) << '\n';
            std::cout << gmean(x,y) << '\n';
            std::cout << "Enter two numbers: ";
        }
        catch (bad& e)
        {
            std::cout << e.what();
            e.reports();
            break;
        }
    }

    return 0;
}

double hmean(double x, double y)
{
    if(x == -y)
        throw bad(x,y);
    return 2.0 * x * y / (x + y);
}

double gmean(double x, double y)
{
    if(x < 0 || y < 0)
        throw bad(x,y);
    return sqrt(x * y);
}

        4. 

#ifndef C_PRIMER_CHAPTER15_SALES_H
#define C_PRIMER_CHAPTER15_SALES_H

#include <stdexcept>
#include <string>

class Sales
{
public:
    enum {MONTHS = 12};
    class bad_index : public std::logic_error
    {
    private:
        int bi;
    public:
        explicit bad_index(int ix, const std::string& s = "Index error in Sales object\n")
        : std::logic_error(s),bi(ix){}
        int bi_val() {return bi;}
        virtual ~bad_index() throw(){}
    };
    explicit Sales(int yy = 0);
    Sales(int yy, const double* gr, int n);
    virtual ~Sales(){}
    int Year() const {return year;}
    virtual double operator[](int i) const;
    virtual double & operator[](int i);
private:
    int year;
    double gross[MONTHS];
};

class LabeledSales : public Sales
{
private:
    std::string label;
public:
    class nbad_index : public bad_index
    {
    private:
        std::string lbl;
    public:
        nbad_index(const std::string & lb, int ix, const std::string & s = "Index error in LabeledSales object\n")
        : bad_index(ix,s),lbl(lb){}
        const std::string & label_val() {return lbl;}
        virtual ~nbad_index(){}
    };
    explicit LabeledSales(const std::string & lb = "none", int yy = 0)
    : Sales(yy),label(lb){}
    LabeledSales(const std::string & lb, int yy, const double* gr, int n)
    : Sales(yy,gr,n),label(lb){}
    virtual ~LabeledSales(){}
    const std::string & Label() const {return label;}
    virtual double operator[](int i) const;
    virtual double & operator[](int i);
};

#endif //C_PRIMER_CHAPTER15_SALES_H
#include "Sales.h"

Sales::Sales(int yy)
{
    year = yy;
    for(int i = 0; i < MONTHS; ++i)
        gross[i] = 0;
}

Sales::Sales(int yy, const double* gr, int n)
{
    year = yy;
    int lim = n < MONTHS ? n : MONTHS;
    int i;
    for(i = 0; i < lim; ++i)
        gross[i] = gr[i];
    for(; i < MONTHS; ++i)
        gross[i] = 0;
}

double Sales::operator[](int i) const
{
    if(i < 0 || i >= MONTHS)
        throw bad_index(i);
    return gross[i];
}

double & Sales::operator[](int i)
{
    if(i < 0 || i >= MONTHS)
        throw bad_index(i);
    return gross[i];
}

double LabeledSales::operator[](int i) const
{
    if(i < 0 || i >= MONTHS)
        throw nbad_index(label,i);
    return Sales::operator[](i);
}
double & LabeledSales::operator[](int i)
{
    if(i < 0 || i >= MONTHS)
        throw nbad_index(label,i);
    return Sales::operator[](i);
}
#include <iostream>
#include "Sales.h"

int main()
{
    using std::cout,std::endl,std::cin;

    using std::cin;
    using std::cout;
    using std::endl;

    double vals1[12] = {1220, 1100, 1122, 2212, 1232, 2334,
                        2884, 2393, 3302, 2922, 3002, 3544};

    double vals2[12] = {12, 11, 22, 21, 32, 34, 28, 29, 33, 29, 32, 35};

    Sales sales1(2011, vals1, 12);
    LabeledSales sales2("Blogstar", 2012, vals2, 12);

    try
    {
        int i;
        cout << "Year = " << sales1.Year() << endl;
        for (i = 0; i < 12; ++i) {
            cout << sales1[i] << ' ';
            if (i % 6 == 5) cout << endl;
        }
        cout << "Year = " << sales2.Year() << endl;
        cout << "Label = " << sales2.Label() << endl;
        for (i = 0; i <= 12; ++i) {
            cout << sales2[i] << ' ';
            if (i % 6 == 5) cout << endl;
        }
        cout << "End of try block 1.\n";
    }
    catch(Sales::bad_index& bad)
    {
        cout << bad.what();
        cout << "Index: " << bad.bi_val() << endl;
        Sales::bad_index* pbad = &bad;
        LabeledSales::nbad_index* pb;
        if((pb = dynamic_cast<LabeledSales::nbad_index*>(pbad)))
        {
            cout << "Company: " << pb->label_val() << endl;
        }
    }
    cout << "\nNext try block:\n";
    try
    {
        sales2[2] = 37.5;
        sales1[20] = 23345;
        cout << "End of try block 2.\n";
    }
    catch (Sales::bad_index &bad)
    {
        cout << bad.what();
        cout << "Index: " << bad.bi_val() << endl;
        if (typeid(bad) == typeid(LabeledSales::nbad_index))
            cout << "Company: " << ((LabeledSales::nbad_index &)bad).label_val() << endl;
    }
    cout << "done\n";

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值