#pragma once
// tv2.h -- Tv and Remote classes
#ifndef __TV2_H__
#define __TV2_H__
class Tv
{
public:
friend class Remote; // Remote can access Tv private parts
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() { state = (state == On) ? Off : On; }
bool isOn() const { return On == state; }
bool volUp();
bool volDown();
void chanUp();
void chanDown();
void set_mode() { mode = (Antenna == mode) ? Cable : Antenna; }
void set_input() { input = (TV == input) ? DVD : TV; }
void setting() const; // display all settings
void set_dispaly_mode(Remote & r);
private:
int state; // on or off
int volume; // assumed to be diginized // 音量
int maxchannel; // maximum number of channels // 最大的电视频道
int channel; // current channel setting // 当前电视频段
int mode; // broadcast or cable //
int input; // TV or DVD
};
class Remote
{
public:
enum { RegularMode, InteractionMode };
private:
int mode; // constrol TV or DVD
int status;
public:
friend class Tv; // TV can access Remote private parts
Remote(int m = Tv::TV, int state = RegularMode) : 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 displayMode() const {
std::cout << "DisplayMode: " << (status == RegularMode ?
"RegularMode" : "InteractionMode") << std::endl;
}
};
#endif /* __TV2_H__ */
// tv2.cpp -- methods for the Tv class (Remote methods are inline)
#include <iostream>
#include "tv2.h"
// class Tv methods
bool Tv::volUp()
{
if (volume < MaxVal) { // MaxVal: 音量的最大值
volume++;
return true;
} else
return false;
}
bool Tv::volDown()
{
if (volume > MinVal) { // MinVal: 音量的最小值
volume--;
return true;
}
else
return false;
}
void Tv::chanUp()
{
if (channel < maxchannel) { // maxchannel: 频道的最大值
channel++;
}
else
channel = 1; // 频道的范围:1 ~ maxchannel
}
void Tv::chanDown()
{
if (channel > 1) { // 1: 频道的最小值
channel--;
}
else
channel = maxchannel; // 频道的范围:1 ~ maxchannel
}
void Tv::setting() const
{
using std::cout;
using std::endl;
cout << "TV is " << (Off == state? "Off" : "On") << endl;
if (On == state) {
cout << "Volume setting = " << volume << endl;
cout << "Channel setting = " << channel << endl;
cout << "Mode = "
<< (mode == Antenna? "antenna" : "cable") << endl;
cout << "Input = "
<< (input == TV? "TV" : "DVD") << endl;
}
}
void Tv::set_dispaly_mode(Remote & r) {
if (On == state) {
r.status = (r.status == Remote::RegularMode)
? Remote::InteractionMode
: Remote::RegularMode;
}
}
/***********************************
2017年12月11日 19:58:29
Athor:xiyuan255
Course:C++
Contain:use_tv2.cpp.cpp
tv2.h
tv2.cpp
Reference: C++ Primer plus
知识点:友元类的应用
总结:如果类A成为类B的友元类,那么类A可以访问类B的私有成员的含义是:
类A可以通过类B对象的引用间接访问类B的私有成员。无法直接使用
类B私有成员名,直接访问。
因为,类A可能不只是类B的的友元类,直接使用私有成员名,无法知道
它是属于哪个类的私有成员。
说明:C++ Primer plus第十五章的练习题 第一题
【 参考 P654 】
*************************************/
// use_tv.cpp -- using the TV and Remote classes
#include <iostream>
#include "tv2.h"
int main()
{
using std::cout;
Tv s42;
Remote grey;
cout << "Initial setting for 42\" TV:\n";
s42.setting();
grey.displayMode();
s42.onOff();
s42.set_dispaly_mode(grey);
grey.displayMode();
s42.chanUp();
cout << "\nAdjusted setting for 42\" TV:\n";
s42.setting();
grey.set_chan(s42, 10);
grey.volUp(s42);
grey.volUp(s42);
cout << "\n42\" setting after using remote:\n";
s42.setting();
return 0;
}
/**
输出结果:
Initial setting for 42" TV:
TV is Off
DisplayMode: RegularMode
DisplayMode: InteractionMode
Adjusted setting for 42" TV:
TV is On
Volume setting = 5
Channel setting = 3
Mode = cable
Input = TV
42" setting after using remote:
TV is On
Volume setting = 7
Channel setting = 10
Mode = cable
Input = TV
*/
#pragma once
// exc_mean2.h -- exception classes for hmean(), gmean()
#ifndef __EXC_MEAN2_H__
#define __EXC_MEAN2_H__
#include <iostream>
#include <stdexcept> // for class logic_error and class runtime_error
class bad_hmean : public std::logic_error
{
public:
bad_hmean(const std::string & str = "bad_hmean(): invalid argument: a = -b")
: logic_error(str) { }
};
class bad_gmean : public std::logic_error
{
public:
bad_gmean(const std::string & str = "gmean() arguments should be >= 0")
: logic_error(str) { }
};
#endif /* __EXC_MEAN2_H__ */
/***********************************
2017年12月11日 20:24:40
Athor:xiyuan255
Course:C++
Contain:pe15-2.cpp
exc_mean2.h
Reference: C++ Primer plus
知识点:异常应用
1.在头文件stdexcept中包含两个从exception异常基类继承而来的
子异常类,分别是logic_error和runtime_error;
2.logic_error类下有一个异常构造函数,参数为const string &
类型,而logic_error类还有一个what的方法,用于logic_error
对象,并把该对象转换为const string 类型。
说明:C++ Primer plus第十五章的练习题 第二题
【 参考 P654 】
*************************************/
// pe15-2.cpp -- using exception classes
#include <iostream>
#include <cmath> // or math.h, unix users may need -lm flag
#include "exc_mean2.h"
// function ptototypes
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 { // start of block
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>: ";
} // end of try block
catch (bad_hmean & bg) { // start of catch block
cout << bg.what() << endl;
cout << "Try again.\n";
continue;
}
catch (bad_gmean & hg) { // start of catch block
cout << hg.what() << endl;
cout << "Sorry, you don't get to play any more.\n";
break;
} // end of catch block
}
std::cout << "Bye!\n";
return 0;
}
/**
输出结果:
Enter two numbers: 4 12
Harmonic mean of 4 and 12 is 6
Geometric mean of 4 and 12 is 6.9282
Enter next set of numbers <q to quit>: 5 -5
bad_hmean(): invalid argument: a = -b
Try again.
5 -2
Harmonic mean of 5 and -2 is -6.66667
gmean() arguments should be >= 0
Sorry, you don't get to play any more.
Bye!
*/
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 std::sqrt(a * b);
}
#pragma once
// exc_mean3.h -- exception classes for hmean(), gmean()
#ifndef __EXC_MEAN3_H__
#define __EXC_MEAN3_H__
#include <iostream>
#include <stdexcept> // for class logic_error and class runtime_error
class bad_base : public std::logic_error
{
private:
double v1;
double v2;
public:
bad_base(const std::string str, double val1, double val2)
: logic_error(str), v1(val1), v2(val2) { }
double v1_val() { return v1; }
double v2_val() { return v2; }
virtual void report() { }
};
class bad_hmean : public bad_base
{
public:
bad_hmean(const std::string str, double a = 0, double b = 0)
: bad_base(str, a, b) { }
virtual void report() {
std::cout << "hmean(" << v1_val() << ", " << v2_val() << "): ";
}
};
class bad_gmean : public bad_base
{
public:
bad_gmean(const std::string str, double a = 0, double b = 0)
: bad_base(str, a, b) { }
virtual void report() {
std::cout << "gmean(" << v1_val() << ", " << v2_val() << "): ";
}
};
#endif /* __EXC_MEAN2_H__ */
/***********************************
2017年12月11日 20:55:55
Athor:xiyuan255
Course:C++
Contain:pe15-3.cpp
exc_mean3.h
Reference: C++ Primer plus
知识点:异常应用
1.基类异常对象引用可以捕获它的所有派生类的异常对象引用;
说明:C++ Primer plus第十五章的练习题 第三题
【 参考 P654 】
*************************************/
// pe15-3.cpp -- using exception classes
#include <iostream>
#include <cmath> // or math.h, unix users may need -lm flag
#include "exc_mean3.h"
// function ptototypes
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 { // start of block
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>: ";
} // end of try block
catch (bad_base & hg) { // start of catch block
hg.report();
cout << hg.what() << endl;
cout << "Sorry, you don't get to play any more.\n";
break;
} // end of catch block
}
std::cout << "Bye!\n";
return 0;
}
/**
输出结果1:
Enter two numbers: 4 12
Harmonic mean of 4 and 12 is 6
Geometric mean of 4 and 12 is 6.9282
Enter next set of numbers <q to quit>: 5 -5
hmean(5, -5): invalid arguments : a = -b
Sorry, you don't get to play any more.
Bye!
输出结果2:
Enter two numbers: 4 12
Harmonic mean of 4 and 12 is 6
Geometric mean of 4 and 12 is 6.9282
Enter next set of numbers <q to quit>: 5 -2
Harmonic mean of 5 and -2 is -6.66667
gmean(5, -2): arguments should be >= 0
Sorry, you don't get to play any more.
Bye!
*/
double hmean(double a, double b)
{
if (a == -b)
throw bad_hmean("invalid arguments : 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("arguments should be >= 0", a, b);
return std::sqrt(a * b);
}
#pragma once
// sales.h -- exceptions and inheritance
#ifndef __SALES_H__
#define __SALES_H__
#include <stdexcept> // stdexcept从exception基类继承而来 for logic_error
#include <string>
class Sales
{
public:
enum { MONTHS = 12 }; // could be a static const
class bad_index : public std::logic_error
{
private:
int bi; // bad index value
public:
explicit bad_index(int ix,
const std::string & s = "Index error in Sales object\n");
int bi_val() const { 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:
double gross[MONTHS];
int year;
};
class LabelSales : public Sales
{
public:
class nbad_index : public Sales::bad_index
{
private:
std::string lb1;
public:
nbad_index(const std::string & lb, int ix,
const std::string & s = "Index error in LabelSales object\n");
const std::string & label_val() const { return lb1; }
virtual ~nbad_index() throw() { }
};
explicit LabelSales(const std::string & lb = "none", int yy = 0);
LabelSales(const std::string & lb, int yy, const double * gr, int n);
virtual ~LabelSales() { }
const std::string & Label() const { return label; }
virtual double operator[](int i) const;
virtual double & operator[](int i);
private:
std::string label;
};
#endif /* __SALES_H__ */
/* programNo15.15 */
// sales.cpp -- Sales implementation
#include "sales.h"
using std::string;
// class Sales methods
Sales::bad_index::bad_index(int ix, const std::string & s)
: std::logic_error(s), bi(ix)
{
}
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 > n and i < MONTHS;
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];
}
// class LabelSales methods
LabelSales::nbad_index::nbad_index(const std::string & lb, int ix,
const std::string & s) : Sales::bad_index(ix, s)
{
lb1 = lb;
}
LabelSales::LabelSales(const std::string & lb, int yy)
: Sales(yy)
{
label = lb;
}
LabelSales::LabelSales(const std::string & lb, int yy, const double * gr,
int n) : Sales(yy, gr, n)
{
label = lb;
}
double LabelSales::operator[](int i) const
{
if (i < 0 || i >= MONTHS)
throw nbad_index(Label(), i);
return Sales::operator[](i);
}
double & LabelSales::operator[](int i)
{
if (i < 0 || i >= MONTHS)
throw nbad_index(Label(), i);
return Sales::operator[](i);
}
/***********************************
2017年12月11日 21:12:45
Athor:xiyuan255
Course:C++
Contain:use_sales2.cpp
sales2.h
sales2.cpp
Reference: C++ Primer plus
说明:C++ Primer plus第十五章的练习题 第四题
【 参考 P654 】
*************************************/
// use_sales.cpp -- nested exceptions
#include <iostream>
#include "sales.h"
int main()
{
using std::cout;
using std::cin;
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);
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;
}
/**
输出结果:
First try block:
Year = 2011
1220 1100 1122 2212 1232 2334
2884 2393 3302 2922 3002 3544
Year = 2012
Label = Blogstar
12 11 22 21 32 34
28 29 33 29 32 35
Index error in LabelSales object
Company: Blogstar
bad_index: 12
Next try block:
Index error in Sales object
bad index: 20
Done.
*/