第十三章类和继承:多态共有继承02
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:多态共有继承
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
二、使用步骤
1.类的实现
代码如下(示例):
//brass.cpp -- bank account class methods
//13.8
#include<iostream>
#include"brass.h"
using std::cout;
using std::endl;
using std::string;
//formatting stuff
typedef std::ios_base::fmtflags format;
typedef std::streamsize precis;
format setFormat();
void restore(format f, precis p);
//Brass methods
Brass::Brass(const string& s, long an, double bal)
{
fullName = s;
acctNum = an;
balance = bal;
}
void Brass::Deposit(double amt)
{
if (amt < 0)
{
cout << "Negative deposit not allowed;" << "deposit is cancelled.\n";
}
else
balance += amt;
}
void Brass::Withdraw(double amt)
{
//set up ###.##format
format initialState = setFormat();
precis prec = cout.precision(2);
if (amt<0)
{
cout << "Withdrawal amount must be positive; "
<< "withdrawal canceled.\n";
}
else if (amt<=balance)
{
balance -= amt;
}
else
{
cout << "Withdrawal amount of $" << amt
<< " exceeds your balance.\n"
<< "Withdrawal canceled.\n";
}
restore(initialState, prec);
}
double Brass::Balance()const
{
return balance;
}
void Brass::ViewAcct()const
{
//set ###.##format
format initialState = setFormat();
precis prec = cout.precision(2);
cout << "Client: " << fullName << endl;
cout << "Account Number: " << acctNum << endl;
cout << "Balance: $" << balance << endl;
restore(initialState, prec);//restore original format
}
//BrassPlus methods
BrassPlus::BrassPlus(const string& s, long an, double bal,
double ml, double r) :Brass(s, an, bal)
{
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
BrassPlus::BrassPlus(const Brass& ba, double ml, double r) :Brass(ba)
{
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
//redefine how wiewacct()works
void BrassPlus::ViewAcct()const
{
//set tup ###.## format
format initialState = setFormat();
precis prec = cout.precision(2);
Brass::ViewAcct();
cout << "Maximum loan:$" << maxLoan << endl;
cout << "Owed to bank: $" << owesBank << endl;
cout.precision(3);
cout << "Loan Rate:" << 100 * rate << "%\n";
restore(initialState, prec);
}
//redefine how withdraw()works
void BrassPlus::Withdraw(double amt)
{
//set up ###.##format
format initialState = setFormat();
precis prec = cout.precision(2);
double bal = Balance();
if (amt<=bal)
{
Brass::Withdraw(amt);
}
else if (amt<= bal + maxLoan-owesBank)
{
double advance = amt - bal;
owesBank += advance * (1.0 - rate);
cout << "Bank advance:$" << advance << endl;
cout << "Finance charge:$" << advance * rate << endl;
Deposit(advance);
Brass::Withdraw(amt);
}
else
{
cout << "Credit limit exceeded.Transaction cancelled.\n";
}
restore(initialState, prec);
}
format setFormat()
{
return cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
}
void restore(format f, precis p)
{
cout.setf(f, std::ios_base::floatfield);
cout.precision(p);
}
1.类的实现具体细节分析
介绍程序清单13.8的具体细节(如一些方法的格式化处理)之前,先来看一下与继承直接相关的方面。记住,派生类并不能直接访问基类的私有数据,而必须使用基类的公有方法才能访问这些数据。访问的方式取决于方法。构造函数使用一种技术,而其他成员函数使用另一种技术。
派生类构造函数在初始化基类私有数据时,采用的是成员初始化列表语法。RatedPlayer类构造函数和BrassPlus 构造函数都使用这种技术:
//BrassPlus methods
BrassPlus::BrassPlus(const string& s, long an, double bal,
double ml, double r) :Brass(s, an, bal)
{
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
BrassPlus::BrassPlus(const Brass& ba, double ml, double r) :Brass(ba)//Uses implicit copy constructor
{
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
这几个构造函数都使用成员初始化列表语法,将基类信息传递给基类构造函数,然后使用构造函数体初始化 BrassPlus 类新增的数据项。
非构造函数不能使用成员初始化列表语法,但派生类方法可以调用公有的基类方法。例如,BrassPlus版本的 ViewAcct()核心内容如下(忽略了格式方面):
//redefine how wiewacct()works
void BrassPlus::ViewAcct()const
{
......
Brass::ViewAcct();
cout << "Maximum loan:$" << maxLoan << endl;
cout << "Owed to bank: $" << owesBank << endl;
cout << "Loan Rate:" << 100 * rate << "%\n";
.....
}
换句话说,BrassPlus::ViewAcct()显示新增的 BrassPlus 数据成员,并调用基类方法 Brass::ViewAcct()来显示基类数据成员。在派生类方法中,标准技术是使用作用域解析运算符来调用基类方法。代码必须使用作用域解析运算符。假如这样编写代码:
//redefine how wiewacct()works
void BrassPlus::ViewAcct()const
{
Brass::ViewAcct();//oops,recursive call
}
如果代码没有使用作用域解析运算符,编译器将认为ViewAcct()是 BrassPlus::ViewAcct(),这将创建
个不会终止的递归函数–这可不好。接下来看 BrassPlus:Withdraw()方法。如果客户提取的金额超过了结余,该方法将安排贷款。它可以使用 Brass::Withdraw()来访问 balance成员,但如果取款金额超过了结余,Brass:Withdraw()将发出一个错误消息。这种实现使用 Deposit()方法进行放贷,然后在得到了足够的结余后调用 Brass::Withdraw,从而避免了错误消息:
//redefine how withdraw()works
void BrassPlus::Withdraw(double amt)
{
....
double bal = Balance();
if (amt<=bal)
{
Brass::Withdraw(amt);
}
else if (amt<= bal + maxLoan-owesBank)
{
double advance = amt - bal;
owesBank += advance * (1.0 - rate);
cout << "Bank advance:$" << advance << endl;
cout << "Finance charge:$" << advance * rate << endl;
Deposit(advance);
Brass::Withdraw(amt);
}
else
{
cout << "Credit limit exceeded.Transaction cancelled.\n";
}
....
}
该方法使用基类的 Balance()函数来确定结余。因为派生类没有重新定义该方法,代码不必对 Balance()使用作用域解析运算符。
方法 ViewAcct()和 Withdraw()使用格式化方法 set()和 precision( )将浮点值的输出模式设置为定点,即包含两位小数。设置模式后,输出的模式将保持不变,因此该方法将格式模式重置为调用前的状态。这与程序清单8.8和程序清单10.5类似。为避免代码重复,该程序将设置格式的代码放在辅助函数中:
//formatting stuff
typedef std::ios_base::fmtflags format;
typedef std::streamsize precis;
format setFormat();
void restore(format f, precis p);
而函数restore()重置格式和精度
void restore(format f, precis p)
{
cout.setf(f, std::ios_base::floatfield);
cout.precision(p);
}
有关设置输出格式的更详细信息,请参阅第十七章
2.使用Brass和BrassPlus类
在下一篇文中中展开
总结
提示:这里对文章进行总结:
暂无

646

被折叠的 条评论
为什么被折叠?



