关于抽象基类

派生类可以直接访问基类中protected的成员,但却不能访问private的成员,其他情况下,两者的作用差不多。最好对类数据成员采用私有访问控制,不要使用保护访问控制;同时用过基类方法使派生类能够访问基类数据。然而,对于成员函数来说,保护访问控制很有效,它让派生类能够访问公共不能使用的内部函数。

下面介绍一下抽象基类:

抽象基类的应用很重要,例如,园是椭圆的一种,可以把圆当成椭圆的派生,但是,这会造成一个问题,椭圆有很多属性,对圆来说是没有用的,这样就会造成信息浪费,但是,椭圆和圆都有一些属性石相同的,因此,我们可以从它两者身上抽象出一个抽象基类ABC,椭圆和圆都可以从它派生出来。

但是,需要注意的是,椭圆和圆的面积计算公式不一样,所以,在抽象基类中可以定义一个纯虚函数。包含虚函数的类只能用于基类。要成为抽象基类,必须包含至少一个纯虚函数。

下面是对上个程序应用抽象基类的改变

acctabc.h

#ifndef ACCTABC_H_
#define ACCTABC_H_
#include<iostream>
#include<string>

class AcctABC
{
public:
	std::string fullName;
	long acctNum;
	double balance;
protected:
	struct Formatting<span style="white-space:pre">							</span>//这是标准结构输出形式,将数据按。。。形式输出
	{<span style="white-space:pre">							</span>
		std::ios_base::fmtflags flag;<span style="white-space:pre">				</span>
		std::streamsize pr;
	};
	const std::string & FullName()const{return fullName;}<span style="white-space:pre">			</span>//不能直接访问fullName?求指导
	long AcctNum()const{return acctNum;}
	Formatting SetFormat()const;
	void Restore(Formatting & f)const;
public:
	AcctABC(const std::string & s="Nullbody",long an=-1,double bal=0);
	void Deposit(double amt);
	virtual void Withdraw(double amt)=0;<span style="white-space:pre">					</span>//这就是纯虚函数
	double Balance()const{return balance;};
	virtual void ViewAcct()const=0;
	virtual ~AcctABC(){}
};

class Brass:public AcctABC
{
public:
	Brass(const std::string &s="Nullbody",long an=-1,double bal=0):AcctABC(s,an,bal){}
	virtual void Withdraw(double amt);
	virtual void ViewAcct()const;
	virtual ~Brass(){}
};

class BrassPlus:public AcctABC
{
private:
	double maxLoan;
	double rate;
	double owesBank;
public:
	BrassPlus(const std::string &s="Nullbody",long an=-1,double bal=0,double max=500,double ra=0.1,double owes=0):AcctABC(s,an,bal)
	{
		maxLoan=max;
		rate=ra;
		owesBank=owes;
	}
	BrassPlus(const AcctABC &ba,double max=500,double ra=0.1,double owes=0):AcctABC(ba){}
	virtual void Withdraw(double amt);
	virtual void ViewAcct()const;
	void ResetMax(double m){maxLoan=m;}
	void ResetRate(double r){rate=r;}
};
#endif
从上面头文件可以看出,构造函数变成了内联函数,这样,他的定义就变成下面:

acctabc.cpp

#include"acctabc.h"

using std::cout;
using std::ios_base;
using std::endl;
using std::string;

AcctABC::AcctABC(const std::string &s,long an,double bal)
{
	fullName=s;
	acctNum=an;
	balance=bal;
}

void AcctABC::Withdraw(double amt)
{
	balance-=amt;
}

void AcctABC::Deposit(double amt)
{
	if(amt<0)
	{
		cout<<"Negative deposit not allowed;"<<"deposit is cancelled."<<endl;
	}
	else
	{
		balance+=amt;
	}
}

AcctABC::Formatting AcctABC::SetFormat()const
{
	Formatting f;
	f.flag=cout.setf(ios_base::fixed,ios_base::floatfield);
	f.pr=cout.precision(2);
	return f;
}

void AcctABC::Restore(Formatting & f)const
{
	cout.setf(f.flag,ios_base::floatfield);
	cout.precision(2);
}

//Brass::Brass(const std::string &s,long an,double bal):AcctABC(s,an,bal)
//{}

void Brass::Withdraw(double amt)
{
	if(amt<0)
	{
		cout<<"Withdrawal amount must be positive; Withdrawal canceled."<<endl;
	}
	else if(amt<Balance())
	{
		balance-=amt;
	}
	else
	{
		cout<<"Withdrawal amount of $"<<amt<<" exceeds your balance."<<endl;
		cout<<"Withdrawal canceled."<<endl;
	}
}

void Brass::ViewAcct()const
{
	Formatting f=SetFormat();
	cout<<"Bras Client:"<<FullName()<<endl;
	/*cout<<"Account Number:"<<acctNum<<endl;*/
	cout<<"Account Number:"<<AcctNum()<<endl;
	cout<<"Balance:$"<<Balance()<<endl;
	Restore(f);
}

//BrassPlus::BrassPlus(const std::string &s,long an,double bal,double ml,double r):AcctABC(s,an,bal)<span style="white-space:pre">	</span>如果不是将构造函数内联到类定义里去了,那么构造函数//就应该这样定义
//{
//	maxLoan=ml;
//	owesBank=0;
//	rate=r;
//}

void BrassPlus::ViewAcct()const
{
	Formatting f=SetFormat();
	cout<<"Bras Client:"<<FullName()<<endl;
//	cout<<"Account Number:"<<acctNum<<endl;   两种方法都可以,可以通过成员函数访问成员变量,也可以直接访问成员变量
	cout<<"Account Number:"<<AcctNum()<<endl;
	cout<<"Balance:$"<<Balance()<<endl;
	cout<<"Maximum loan:$"<<maxLoan<<endl;
	cout<<"owed to bank:$"<<owesBank<<endl;
	cout.precision(3);
	cout<<"Loan Rate:"<<100*rate<<"%"<<endl;
	Restore(f);
}

void BrassPlus::Withdraw(double amt)
{
	Formatting f=SetFormat();

	if(amt<0)
	{
		cout<<"Withdrawal amount must be positive; Withdrawal canceled."<<endl;
	}
	else if(amt<balance)
	{
		balance-=amt;
	}
	else if(amt<(balance+maxLoan-owesBank))
	{
		owesBank=(amt-balance)*(1+rate);
		cout<<"Bank advance:$"<<(amt-balance)<<endl;
		cout<<"Finance charge:$"<<(amt-balance)*rate<<endl;
		balance=0;
	}
	else
	{
		cout<<"Credit limit exceeded.Transaction cancelled."<<endl;
	}
	Restore(f);
}
usebrass3.cpp

#include"acctabc.h"

const int clients=4;

int main()
{
	using namespace std;
	AcctABC *p_clients[clients];
	std::string temp;
	long tempnum;
	double tempbal;
	char kind;

	for(int i=0;i<clients;i++)
	{
		cout<<"Enter clients' 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 eighter 1 or 2:";
		if(kind=='1')
			p_clients[i]=new Brass(temp,tempnum,tempbal);
		else/* if(kind=='2')*/
		{
			double tmax,trate;
			cout<<"Enter the overdraft limit:$";
			cin>>tmax;
			cout<<"Enter the interest 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."<<endl;

	system("pause");
	return 0;
}
由于对象时指针,所以按指针指向的类型调用函数,而不是按指针的类型调用函数



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值