c++ Primer Plus(习题15.1)
//对书上的友元类进行成员的增加
// 一种简单的修改
#include<iostream>
#include"tv.h"
int main()
{
using std::cout;
Tv s42;
cout << "Initial settings for 42: \n";
s42.settings();
s42.onoOff();
cout << "\nAffter settinfs: \n ";
s42.settings();
Remote grey;
grey.chanup(s42);
grey.volup(s42);
s42.set_style(grey);
cout << "\nAffter setting: \n";
s42.settings();
grey.showstyle();
return 0;
}
#pragma once
#pragma execution_character_set("utf-8")
//本文件为utf-8编码格式
//书上的友元类的程序清单,顺便做15.1题目,增加一个成员
#ifndef TV_H
#define TV_H
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(5),mode(Cable),input(TV){} //默认构造函数
void onoOff() { state ^= 1; } //切换模式,按位异或
bool ison()const { return state == On; } //检查电视是否打开的方法
bool volup(); //调整音量的方法
bool voldown();
void chanup(); //调整频道的方法
void chandown();
void set_style(Remote &r);
//调整互动模式或者是常规模式的方法
void set_mode() { mode ^= 1; }
void set_input() { input ^= 1; }
void settings()const;
private:
int state;
int volume;
int maxchannel;
int channel;
int mode;
int input;
};
class Remote
{
private:
int mode;
int style;
public:
friend class Tv; //让他们互相成为友元,Tv才能使用更改,Romote的style成员
enum { Normal, Action };
Remote(int m = Tv::TV):mode(m),style(Normal) {};
bool volup(Tv&t) { return t.volup(); }; //括号外面可以不加冒号
bool voldown(Tv&t) { return t.voldown(); };
void onoff(Tv&t) { t.onoOff(); }
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 showstyle()const;
};
#endif // !TV_H
//tv头文件的实现方法
#include<iostream>
#include"tv.h"
bool Tv::volup()
{
if (volume <MaxVal)
{
volume++;
return true;
}
else
return false;
}
bool Tv::voldown()
{
if (volume > MinVal)
{
volume--;
return true;
}
else
return false;
}
void Tv::chanup()
{
if (channel < maxchannel)
channel++;
else
channel = 1; //频道调整是设置成循环,当到达最大值,重新设置为第一个频道
}
void Tv::chandown()
{
if (channel > 1)
channel--;
else
channel = maxchannel;
}
void Tv::settings()const
{
using std::cout;
using std::endl;
cout << "TV is " << (state == Off ? "Off" : "On") << endl;
if (state == On)
{
cout << "Volume setting = " << volume << endl;
cout << "Channel setting = " << channel << endl;
cout << "Mode = "
<< (mode == Antenna ? "antenna" : "cable") << endl;
cout << "Iuput = "
<< (input == TV ? "TV" : "DVD") << endl;
}
}
void Tv::set_style(Remote&r)
{
if (state == 1)
r.style ^= 1; //接受的是一个遥控器对象,竟然无法更改私有成员
}
void Remote::showstyle()const
{
std::cout << "Style = "
<< (style==Normal?"Normal":"Action")<< std::endl;
}
c++ Primer Plus(习题15.2)
//派生一个异常类以excception派生
//并修改程序清单15.11,让what方法报告错误的函数名和问题性质
#include<iostream>
#include<exception>
class bad_hmean :public std::exception //Hanomic error class
{
private:
double v1;
double v2;
public:
const char* what()
{ return "bad argument to hmean(),invalid argument:a=-b\n"; }
bad_hmean(double a = 0, double b = 0) :v1(a), v2(b) {};
};
class bad_gmean :public std::exception //Geometric error class
{
private:
double v1;
double v2;
public:
const char* what() { return "bad argument to gmean(),argument shoule be >=0\n"; }
bad_gmean(double a = 0, double b = 0) :v1(a), v2(b) {};
};
double hmean(double a, double b);
double gmean(double a, double b);
int main()
{
using std::cout;
using std::cin;
using std::endl;
double x, y, z;
cout << "Enter two numbers: ";
while (cin >> x >> y)
{
try
{
z = hmean(x, y);
cout << "Hanomic mean of " << x << " and " << y << " is " << z << endl;
cout << "Geometric mean of " << x << " and " << y << " is " << gmean(x, y) << endl;
cout << "Enter the next set of numbers<q to exit>";
}//使用try块
catch (bad_gmean&bg) //捕捉异常输入
{
cout<<bg.what();
cout << "Try again.\n";
continue;
}
catch (bad_hmean&hg) //捕捉异常输入
{
cout<<hg.what();
cout << "Sorry,you don't get to play any more.\n";
break;
}
}
cout << "Bye!\n";
return 0;
}
double hmean(double a, double b)
{
if (a == -b)
throw bad_hmean(a, b);
return 2.0*a*b / (a + b);
}
double gmean(double a, double b)
{
if (a<0||b<0)
throw bad_gmean(a, b);
return std::sqrt(a*b);
}
c++ Primer Plus(习题15.3)
//这题跟前面那题差不多,不过要从一个异常基类中派生出来
//这样就具有多态性,根据错类型来调用方法
//并修改程序清单15.11,让what方法报告错误的函数名和问题性质
#include<iostream>
class logic_error
{
protected:
double v1;
double v2;
public:
logic_error(double a = 0, double b = 0) :v1(a), v2(b) {};
virtual void Report() {}; //虚函数,花括号必须的,不然vs2015链接错误
};
class bad_hmean:public logic_error //Hanomic error class
{
public:
virtual void Report()
{
std::cout << "bad argument to hmean(),invalid argument:a=-b\n"
<< "You input " << logic_error::v1 << "=" << logic_error::v2 << std::endl;
}
bad_hmean(double a = 0, double b = 0) :logic_error(a,b) {};
};
class bad_gmean :public logic_error //Geometric error class
{
public:
virtual void Report()
{
std::cout<<"bad argument to gmean(),argument shoule be >=0\n"
<< "You input " << logic_error::v1 << " or " << logic_error::v2 <<" <0"<< std::endl;
}
bad_gmean(double a = 0, double b = 0) :logic_error(a,b) {};
};
double hmean(double a, double b);
double gmean(double a, double b);
int main()
{
using std::cout;
using std::cin;
using std::endl;
double x, y, z;
cout << "Enter two numbers: ";
while (cin >> x >> y)
{
try
{
z = hmean(x, y);
cout << "Hanomic mean of " << x << " and " << y << " is " << z << endl;
cout << "Geometric mean of " << x << " and " << y << " is " << gmean(x, y) << endl;
cout << "Enter the next set of numbers<q to exit>";
}//使用try块
catch (logic_error&hg) //捕捉异常输入
{
hg.Report();
cout << "Sorry,you don't get to play any more.\n";
break;
}
}
cout << "Bye!\n";
return 0;
}
double hmean(double a, double b)
{
if (a == -b)
throw bad_hmean(a, b);
return 2.0*a*b / (a + b);
}
double gmean(double a, double b)
{
if (a<0 || b<0)
throw bad_gmean(a, b);
return std::sqrt(a*b);
}
c++ Primer Plus(习题15.4)
//这题修改书上的代码,这总比自己写容易点,不过还是要打代码 //省不了的事,修改程序用一个catch来捕捉非法索引错误 //而且要使用RTTI运行阶段类型识别的特性 //说白了还是类的多态性,看需要调用哪个类的方法 #include "sales.h" #include <iostream> int main() { 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); std::cout << "First try block:\n"; try { int i; std::cout << "Year = " << sales1.Year() << std::endl; for (i = 0; i < 12; ++i) { std::cout << sales1[i] << ' '; if (i % 6 == 5) std::cout << std::endl; } std::cout << "Year = " << sales2.Year() << std::endl; std::cout << "Label = " << sales2.Label() << std::endl; for (i = 0; i <= 12; ++i) { std::cout << sales2[i] << ' '; if (i % 6 == 5) std::cout << std::endl; } std::cout << "End of try block 1.\n"; } catch (std::logic_error &le) //祖先基类,引用派生类 { std::cout << le.what(); //what方法接受一个string字符串 if (LabeledSales::nbad_index *ni = dynamic_cast<LabeledSales::nbad_index *>(&le)) { //看能否安全转换,意思是多态性 std::cout << "Company: " << ni->label_val() << std::endl; std::cout << "bad index: " << ni->bi_val() << std::endl; } else if (Sales::bad_index *bi = dynamic_cast<Sales::bad_index *>(&le)) std::cout << "bad index: " << bi->bi_val() << std::endl; } std::cout << "\nNext try block:\n"; try { sales2[2] = 37.5; sales1[20] = 23345; std::cout << "End of try block 2.\n"; } catch (std::logic_error &le) { //都是这样改,就这么简单 std::cout << le.what(); if (LabeledSales::nbad_index *ni = dynamic_cast<LabeledSales::nbad_index *>(&le)) { std::cout << "Company: " << ni->label_val() << std::endl; std::cout << "bad index: " << ni->bi_val() << std::endl; } else if (Sales::bad_index *bi = dynamic_cast<Sales::bad_index *>(&le)) std::cout << "bad index: " << bi->bi_val() << std::endl; } return 0; }