C++ Primer Plus第十五章练习

15.8.1
很简单 只需要多添加2个方法和一个状态就行 不过令我不解的是为什么需要将remote前向声明
tv.h

#ifndef TV_H
#define TV_H
#include <iostream>
using namespace std;
class Remote;//????这是为何 书上说如果声明为友元类就不需要前向声明了 如果没有这个不通过编译
class Tv
{
public:
    friend class Remote;
    enum { Off, On };
	enum { MinVal, MaxVal = 20 };
	enum { Antenna, Cable };
	enum { TV, DVD };
    Tv(int s = Off, int mc = 125) : state(s), volume(5),
		maxchannel(mc), channel(2), mode(Cable), input(TV) { }
	void onOff(void) { state = (state == On) ? Off : On; }
	bool isOn(void) const { return On == state; }
	bool volUp(void);
	bool volDown(void);
	void chanUp(void);
	void chanDown(void);
	void set_mode(void) { mode = (Antenna == mode) ? Cable : Antenna; }
	void set_input(void) { input = (TV == input) ? DVD : TV; }
	void setting(void) const;
    void setstate(Remote &);
private:
    int state;
	int volume;
	int maxchannel;
	int channel;
	int mode;
	int input;
};
class Remote
{
private:
    enum state{normal, interactive};
	int mode;
    int status;
public:
	friend class Tv;  
    Remote(int m = Tv::TV, int state = normal) : mode(m), status(state){ }
	bool volUp(Tv & t) { return t.volUp(); }
	bool volDown(Tv & t) { return t.volDown(); }
	void onOff(Tv & t) { t.onOff(); }
	void chanUp(Tv & t) { t.chanUp(); }
	void chanDown(Tv & t) { t.chanDown(); }
	void set_chan(Tv & t, int c) { t.channel = c; }
	void set_mode(Tv & t) { t.set_mode(); }
	void set_input(Tv & t) { t.set_input(); }
    void showmode(void) const
    {
        cout << "Now mode is:" << (status == normal ? "normal" : "interactive") << endl;
    }
};
#endif

15.8.2
题意是让我们将使用logic_error派生出gmean与hmean且这2个类不需要存储值只需要支持what方法即可
error.h

#ifndef ERROR_H
#define ERROR_H
#include <stdexcept>
#include <iostream>
using namespace std;
class bad_hmean : public logic_error
{
public:
    bad_hmean(const string & s = "bad_hmean(): invalid argument: a = -b") : logic_error(s) {}
};
class bad_gmean : public logic_error
{
public:
    bad_gmean(const string & s = "bad_gmean(): arguments should be >= 0") : logic_error(s) {}
};
#endif

main.cpp

#include "error.h"
#include <cmath>
double hmean(double, double);
double gmean(double, double);
int main(void)
{
    double x, y, z;
	cout << "Enter two numbers: ";
	while (cin >> x >> y)
    {
		try 
        {
			z = hmean(x, y);
			cout << "Harmonic mean of " << x << " and " << y
				<< " is " << z << endl;
			cout << "Geometric mean of " << x << " and " << y
				<< " is " << gmean(x, y) << endl;
			cout << "Enter next set of numbers <q to quit>: ";
		}
		catch (bad_hmean & bg) 
        { 
			cout << bg.what() << endl;
			cout << "Try again.\n";
			continue;
		}
		catch (bad_gmean & hg) 
        {
			cout << hg.what() << endl;
			cout << "Sorry, you don't get to play any more.\n";
			break;
		}
	}
}
double hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean();
	return 2.0 * a * b / (a + b);
}
double gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean();
	return sqrt(a * b);
}

15.8.3
error.h
刚开始想的是logic_error分别派生2个类 写完发现没法调用显示函数 然后就改成多重派生结构

#ifndef ERROR_H
#define ERROR_H
#include <stdexcept>
#include <iostream>
using namespace std;
class bad_hmean : public logic_error
{
private:
    double a;
    double b;
public:
    bad_hmean(const string & s, double n1, double n2) : logic_error(s), a(n1), b(n2) {}
    virtual void show(void) const
    {
        cout << "bad_hmean() " << "a: " << a << " b: " << b << endl;
    }
};
class bad_gmean : public bad_hmean
{
private:
    double a;
    double b;
public:
    bad_gmean(const string & s, double n1, double n2) : bad_hmean(s, n1, n2) {}
    virtual void show(void) const
    {
        cout << "bad_gmean() " << "a: " << a << " b: " << b << endl;
    }
};
#endif

main.cpp

#include "error.h"
#include <cmath>
double hmean(double, double);
double gmean(double, double);
int main(void)
{
    double x, y, z;
	cout << "Enter two numbers: ";
	while (cin >> x >> y)
    {
		try 
        {
			z = hmean(x, y);
			cout << "Harmonic mean of " << x << " and " << y
				<< " is " << z << endl;
			cout << "Geometric mean of " << x << " and " << y
				<< " is " << gmean(x, y) << endl;
			cout << "Enter next set of numbers <q to quit>: ";
		}
		catch (bad_hmean & bg) 
        {
            bg.show();
			cout << bg.what() << endl;
			cout << "Try again.\n";
			break;
		}
	}
}
double hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean("bad_hmean(): invalid argument: a = -b", a, b);
	return 2.0 * a * b / (a + b);
}
double gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean("bad_gmean(): arguments should be >= 0", a, b);
	return sqrt(a * b);
}

15.8.4
配合这个https://blog.csdn.net/xiyuan255/article/details/79224960看半天才看懂
原本的测试文件是分别捕获2种异常然后分别写出遇到异常之后的方法
现在的测试文件只需要捕获基类异常利用RTTI中dynamic_cast运算符来判断当前异常这个是否能转换到派生类异常中 能转换代表他本来就是派生类的异常 label_val()函数则有意义 不能转换就代表他是基类中的异常 此时就不需要调用label_val()
这样就符合了题意 每个try下只有一个catch
main.cpp

#include "sales.h"
int main(void)
{
    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);
	LabelSales sales2("Blogstar", 2012, vals2, 12);
	cout << "First try block:\n";
	try {
		int i;
		cout << "Year = " << sales1.Year() << endl;
		for (i = 0; i < 12; i++) {
			cout << sales1[i] << ' ';
			if (5 == i % 6)
				cout << endl;
		}
		cout << "Year = " << sales2.Year() << endl;
		cout << "Label = " << sales2.Label() << endl;
		for (i = 0; i <= 12; i++) {
			cout << sales2[i] << ' ';
			if (5 == i % 6)
				cout << endl;
		}
		cout << "End of try block 1.\n";
	} catch (Sales::bad_index & bad) {
		cout << bad.what();
		if (LabelSales::nbad_index * p = dynamic_cast<LabelSales::nbad_index *> (&bad))
			cout << "Company: " << p->label_val() << endl;
		cout << "bad index: " << bad.bi_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();
		if (LabelSales::nbad_index * p = dynamic_cast<LabelSales::nbad_index *> (&bad))
			cout << "Company: " << p->label_val() << endl;
		cout << "bad index: " << bad.bi_val() << endl;
	}
	cout << "Done.\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值