抽象基类
eg
当基类和派生类都采用动态内存分配时,派生类的析造函数、复制构造函数及赋值操作符都必须使用相应的基类方法来处理基类元素
析构函数是自动完成
构造函数是通过初始化成员列表中基类的复制构造函数来完成
赋值操作符,通过使用作用域解析操作符显示地调用基类的赋值操作符
eg
eg
acctABC.h
#ifndef ACCTABC_H_ #define ACCTABC_H_ //Abstract Base Class class AcctABC { private: enum{MAX = 35}; char fullName[MAX]; long acctNum; double balance; protected: const char *FullName()const{return fullName;} long AcctNum()const{return acctNum;} std::ios_base::fmtflags SetFormat()const; public: AcctABC(const char *s = "Nullbody",long an = -1,double bal = 0.0); void Deposit(double amt); //pure virtual function virtual void Withdraw(double amt) = 0; double Balance()const{return balance;}; //pure virtual function virtual void ViewAcct()const = 0; virtual ~AcctABC(){} }; //Brass Account Class class Brass:public AcctABC { public: Brass(const char *s = "Nullbody",long an = -1,double bal = 0.0):AcctABC(s,an,bal){} virtual void Withdraw(double amt); virtual void ViewAcct()const; virtual ~Brass(){} }; //Brass Plus Account Class class BrassPlus:public AcctABC { private: double maxLoan; double rate; double owesBank; public: BrassPlus(const char *s = "Nullbody",long an = -1,double bal = 0.0,double ml = 500,double r = 0.10); BrassPlus(const Brass & ba,double ml = 500,double r = 0.1); 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
acctABC.cpp
#include <iostream> #include <cstring> #include "acctabc.h" using std::cout; using std::endl; using std::ios_base; AcctABC::AcctABC(const char *s,long an,double bal) { std::strncpy(fullName,s,MAX-1); fullName[MAX-1] = '\0'; acctNum = an; balance = bal; } void AcctABC::Deposit(double amt) { if(amt < 0) cout<<"Negative deposit not allowed;deposit is cancelled.\n"; else balance += amt; } void AcctABC::Withdraw(double amt) { balance -= amt; } //protected method ios_base::fmtflags AcctABC::SetFormat()const { ios_base::fmtflags initialState = cout.setf(ios_base::fixed,ios_base::floatfield); cout.setf(ios_base::showpoint); cout.precision(2); return initialState; } //Brass methods void Brass::Withdraw(double amt) { if(amt < 0) cout<<"Withdrawal amount must be positive;withdrawal canceled.\n"; else if(amt <= Balance()) AcctABC::Withdraw(amt); else cout<<"Withdrawal amount of {1}quot;<<amt<<" exceeds your balance.\nWithdrawal canceled.\n"; } void Brass::ViewAcct()const { ios_base::fmtflags initialState = SetFormat(); cout<<"Brass Client: "<<FullName()<<endl; cout<<"Account Number: "<<AcctNum()<<endl; cout<<"Balance:$ "<<Balance()<<endl; cout.setf(initialState); } //BrassPlus method BrassPlus::BrassPlus(const char *s,long an,double bal,double ml,double r):AcctABC(s,an,bal) { maxLoan = ml; owesBank = 0.0; rate = r; } BrassPlus::BrassPlus(const Brass &ba,double ml,double r):AcctABC(ba) { maxLoan = ml; owesBank = 0.0; rate = r; } void BrassPlus::ViewAcct()const { ios_base::fmtflags initialState = SetFormat(); cout<<"BrassPlus Client: "<<FullName()<<endl; cout<<"Account Number: "<<AcctNum()<<endl; cout<<"Balance:{1}quot;<<Balance()<<endl; cout<<"Maximum loan:{1}quot;<<maxLoan<<endl; cout<<"Owed to bank:{1}quot;<<owesBank<<endl; cout<<"Loan Rate: "<<100*rate<<"%\n"; cout.setf(initialState); } void BrassPlus::Withdraw(double amt) { ios_base::fmtflags initialState = SetFormat(); double bal = Balance(); if(amt <= bal) AcctABC::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); AcctABC::Withdraw(amt); } else cout<<"Credit limit exceeded.Transaction cancelled.\n"; cout.setf(initialState); }
usebrass3.cpp
继承和动态内存分配#include <iostream> #include "acctabc.h" const int CLIENTS = 4; const int LEN = 40; int main() { using std::cin; using std::cout; using std::endl; //指针表达Brass与BrassPlus AcctABC * p_clients[CLIENTS]; int i; for(i = 0;i<CLIENTS;i++) { char temp[LEN]; long tempnum; double tempbal; char kind; cout<<"Enter client's name:"; cin.getline(temp,LEN); cout<<"Enter client's account number:"; cin>>tempnum; cout<<"Enter opening balance:{1}quot;; 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构造Brass类对象 p_clients[i] = new Brass(temp,tempnum,tempbal); else { double tmax,trate; cout<<"Enter the interest rate as a decimal fraction: "; cin>>trate; //p_client构造BrassPlus类对象 p_clients[i] = new BrassPlus(temp,tempnum,tempbal,tmax,trate); } while(cin.get()!='\n') continue; } cout<<endl; for(i=0;i<CLIENTS;i++) { p_clients[i]->ViewAcct(); cout<<endl; } for(i = 0;i<CLIENTS;i++) { delete p_clients[i]; } cout<<"Done!\n"; system("pause"); return 0; }
当基类和派生类都采用动态内存分配时,派生类的析造函数、复制构造函数及赋值操作符都必须使用相应的基类方法来处理基类元素
析构函数是自动完成
构造函数是通过初始化成员列表中基类的复制构造函数来完成
赋值操作符,通过使用作用域解析操作符显示地调用基类的赋值操作符
eg
dma.h
#ifndef DMA_H_ #define DMA_H_ #include <iostream> //class base class baseDMA { private: char *label; int rating; public: baseDMA(const char *l="null",int r = 0); baseDMA(const baseDMA &rs); virtual ~baseDMA(); baseDMA & operator = (const baseDMA & rs); friend std::ostream & operator<<(std::ostream & os,const baseDMA & rs); }; //derived class class lacksDMA:public baseDMA { private: enum{COL_LEN = 40}; char color[COL_LEN]; public: lacksDMA(const char *c = "blank",const char *l = "null",int r= 0); lacksDMA(const char *c,const baseDMA & rs); friend std::ostream & operator<< (std::ostream & os,const lacksDMA & rs); }; //derived class class hasDMA:public baseDMA { private: char * style; public: hasDMA(const char *s = "none",const char *l = "null",int r = 0); hasDMA(const char *s,const baseDMA & rs); hasDMA(const hasDMA & hs); ~hasDMA(); hasDMA & operator=(const hasDMA & rs); friend std::ostream & operator<<(std::ostream & os,const hasDMA & rs); }; #endif
dma.cpp
#include "dma.h" #include <cstring> //baseDMA method baseDMA::baseDMA(const char * l,int r) { label = new char[std::strlen(l)+1]; std::strcpy(label,l); rating = r; } baseDMA::baseDMA(const baseDMA & rs) { label = new char[std::strlen(rs.label)+1]; std::strcpy(label,rs.label); rating = rs.rating; } baseDMA::~baseDMA() { delete []label; } baseDMA & baseDMA::operator=(const baseDMA & rs) { if(this == &rs) return *this; delete []label; label = new char[std::strlen(rs.label)+1]; std::strcpy(label,rs.label); rating = rs.rating; return *this; } std::ostream & operator<<(std::ostream & os,const baseDMA & rs) { os<<"Label: "<<rs.label<<std::endl; os<<"Rating: "<<rs.rating<<std::endl; return os; } //lacksDMA method lacksDMA::lacksDMA(const char *c,const char *l,int r):baseDMA(l,r) { std::strncpy(color,c,39); color[39] = '\0'; } lacksDMA::lacksDMA(const char *c,const baseDMA & rs):baseDMA(rs) { std::strncpy(color,c,COL_LEN-1); color[COL_LEN-1] = '\0'; } std::ostream & operator<<(std::ostream & os,const lacksDMA & ls) { os<<(const baseDMA & )ls; os<<"Color: "<<ls.color<<std::endl; return os; } //hasDMA method hasDMA::hasDMA(const char *s,const char *l,int r ):baseDMA(l,r) { style = new char[std::strlen(s)+1]; std::strcpy(style,s); } hasDMA::hasDMA(const char *s,const baseDMA &rs):baseDMA(rs) { style = new char[std::strlen(s)+1]; std::strcpy(style,s); } hasDMA::hasDMA(const hasDMA & hs):baseDMA(hs) { style = new char[std::strlen(hs.style)+1]; std::strcpy(style,hs.style); } hasDMA::~hasDMA() { delete []style; } hasDMA & hasDMA::operator=(const hasDMA & hs) { if(this == &hs) return *this; baseDMA::operator=(hs);//copy base protion style = new char[std::strlen(hs.style)+1]; std::strcpy(style,hs.style); return *this; } std::ostream & operator<<(std::ostream & os,const hasDMA & hs) { os<<(const baseDMA & )hs; os<<"Style: "<<hs.style<<std::endl; return os; }
usedma.cpp
#include <iostream> #include "dma.h" int main() { using std::cout; using std::endl; baseDMA shirt("Protabelly",8); lacksDMA balloon("red","Blimpo",4); hasDMA map("Mercator","Buffalo Keys",5); cout<<shirt<<endl; cout<<balloon<<endl; cout<<map<<endl; lacksDMA balloon2(balloon); hasDMA map2; map2 = map; cout<<balloon2<<endl; cout<<map2<<endl; system("pause"); return 0; }
成员函数属性