IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 2021-9-7 C++Primer Plus 类继承 (1) -> 正文阅读

[C++知识库]2021-9-7 C++Primer Plus 类继承 (1)

实例导入:

brass.h

//brass.h -- bank account classes
#ifndef BRASS_H_
#define BRASS_H_
#include <string>

//Brass Account Class
class Brass
{
private:
	std::string fullName;
	long acctNum;
	double balance;
public:
	Brass(const std::string& s = "Nullbody", long an = -1, double bal = 0.0);
	void Deposit(double amt);
	virtual void Withdraw(double amt);
	double Balance() const;
	virtual void ViewAcct() const;
	virtual ~Brass() {}
};

//Brass Plus Account Class
class BrassPlus :public Brass
{
private:
	double maxLoan;
	double rate;
	double owesBank;
public:
	BrassPlus(const std::string& s = "Nullbody", long an = -1, double bal = 0.0, double m1 = 500, double r = 0.11125);
	BrassPlus(const Brass& ba, double ml = 500, double r = 0.11125);
	virtual void ViewAcct()const;
	virtual void Withdraw(double amt);
	void ResetMax(double m) { maxLoan = m; }
	void ResetRate(double r) { rate = r; }
	void ResetOwes() { owesBank = 0; }
};


#endif

brass.cpp

//brass.cpp -- bank account class methods
#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 canselled.\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." << endl;
	else if (amt <= balance)
		balance -= amt;
	else
		cout << "Withdraw amount of $" << amt << " exceds your balance." << endl << "Withdrawal canceled.\n";
	restore(initialState, prec);
}

double Brass::Balance() const
{
	return balance;
}

void Brass::ViewAcct() const
{
	//set up 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);
}

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 ViewAcct() works
void BrassPlus::ViewAcct() const
{
	//set up 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);
}

usebrass.cpp

//usebrass2.cpp -- polymorphic example
//compile with brass.cpp
#include<iostream>
#include<string>
#include"brass.h"
const int CLIENTS = 4;

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

	Brass* p_clients[CLIENTS];
	std::string temp;

	long tempnum;
	double tempbal;
	char kind;

	for (int i = 0; i < CLIENTS; i++)
	{
		cout << "Enter client's name: ";
		getline(cin, temp);
		cout << "Enter client's account number: ";
		cin >> tempnum;
		cout << "Enter opening balance: $";
		cin >> tempbal;
		cout << "Enter 1 for Brass Account or " << "2 for BrassPlus Account: ";
		while (cin >> kind && (kind != '1' && kind != '2'))
			cout << "Enter either 1 or 2: ";
		if (kind == '1')
			p_clients[i] = new Brass(temp, tempnum, tempbal);
		else
		{
			double tmax, trate;
			cout << "Enter the overdraft limit: $";
			cin >> tmax;
			cout << "Enter the interst rate " << "as a decimal fraction: ";
			cin >> trate;
			p_clients[i] = new BrassPlus(temp, tempnum, tempbal, tmax, trate);
		}
		while (cin.get() != '\n')
			continue;
	}
	cout << endl;
	for (int i = 0; i < CLIENTS; i++)
	{
		p_clients[i]->ViewAcct();
		cout << endl;
	}

	for (int i = 0; i < CLIENTS; i++)
	{
		delete p_clients[i];
	}
	cout << "Done.\n";
	return 0;
}

代码解析:

(1)

class BrassPlus :public Brass
{
    ……
}

从一个类派生另一个类时,原始类称为基类,继承类称为派生类,需使用关键字public

基类的公有成员将成为派生类的公有成员:基类的私有部分也会成为派生类的一部分,但只能通过

基类的公有和保护方法访问。

(2)成员初始化列表:

Brass::Brass(const string& s, long an, double bal) :fullName(s),
 acctNum(an), balance(bal){}

初始化列表语法可直接使用string的复制构造函数将fullName初始化为s。如果不使用初始化列表,

会先调用string的默认构造函数再调用赋值运算符将fullName初始化为s,增加一个步骤导致所用时

间变长。

(3)

BrassPlus::BrassPlus(const Brass& ba, double ml, double r) :Brass(ba)
{
	maxLoan = ml;
	owesBank = 0.0;
	rate = r;
}

派生类的构造函数必须使用基类的构造函数,因此可以使用成员初始化列表将BrassPlus中属于

Brass的部分初始化为ba,其余类成员可按一般办法初始化。

(4)

Brass* p_clients[CLIENTS];
    ……
if (kind == '1')
	p_clients[i] = new Brass(temp, tempnum, tempbal);
else
{
    double tmax, trate;
    cout << "Enter the overdraft limit: $";
    cin >> tmax;
	cout << "Enter the interst rate " << "as a decimal fraction: ";
	cin >> trate;
	p_clients[i] = new BrassPlus(temp, tempnum, tempbal, tmax, trate);
}

基类指针或引用只能用于调用基类方法,但是基类指针可以在不进行显示类型转换的情况下指向派

生类对象,基类引用也是类似。同时,不可以将基类对象和地址赋给派生类引用和指针。

(5)

	virtual void Withdraw(double amt);

    ……

    virtual void Withdraw(double amt);

虚方法:类在声明类方法时在前添加关键字virtual,这种方法成为虚方法。

如果没有使用关键字virtual,程序将根据引用类型或指针类型选择方法;如果使用了virtual,程序

将根据引用或指针指向的对象的类型来选择方法。

	virtual ~Brass() {}

虚析构函数是为了确保释放派生对象时,按正确的顺序调用析构函数,依次释放派生类new分配的

内存和基类new分配的内存。

Brass指针既可以指向Brass对象,也可以指向BrassPlus对象,因此可以使用一个数组来表示多种

类型的对象,这就是多态性。

(6)

typedef std::ios_base::fmtflags format;
typedef std::streamsize precis;
format setFormat();
void restore(format f, precis p);

为避免代码重复,该程序将设置格式的代码放在辅助函数内。

代码在使用过程中,设置模式后,输出的模式不变,可以将格式模式重置为调用前的状态。

(7)

void BrassPlus::ViewAcct() const
{
    ……

	Brass::ViewAcct();

    ……

}

在派生类中使用类方法需要加上作用域解析运算符,不然可能会创建一个不会终止的递归函数。

(8)

		while (cin >> kind && (kind != '1' && kind != '2'))
			cout << "Enter either 1 or 2: ";

在输入kind的同时还能检测是否输入正确,输入错误还需要及时修改!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 10:29:29  更:2021-09-08 10:30:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:00:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码