C++如何在派生类成员函数内调用基类的成员函数(包括构造函数)
2014-11-14 17:53
796 查看
前段时间在实现一段代码的过程中遇到了几个相当简单却对于久疏C++战阵的人来说挺烦人的问题:
(而且在网上查了好久才在字里行间寻找到答案)
1.如何定义子类的构造函数,或者说如何在子类构造函数中调用父类的构造函数来实现对成员变量的初始化。
2.Const 成员函数的意义。
3.如何在派生类成员函数中调用基类的成员函数。
4.基类的私有成员是不能被派生类直接访问的,只有通过调用基类的公有方法(对私有成员修改的方法)才能实现
对基类私有成员的访问。
下面我们逐个解决前三个问题,并在解决完问题以后给出一个完整的例子:
1.如何在子类构造函数中调用基类的构造函数。
假设我有一个基类Account和一个派生类SavingAccount,SavingAccount除了继承了Account基类的一个balance变量外,自己也有一个interestrate变量。Account基类的构造函数如下:Account::Account(double ba)
{
balance = ba;
}那么派生类调用基类构造方法来实现自己的构造方法并对成员进行初始化的定义为:
SavingAccount::SavingAccount(double ba, double inte) :Account(ba)
{
// balance = ba;
interestrate = inte;
}
利用基类的构造函数来实现对派生类从基类继承得到的成员变量的初始化,利用自己的构造函数来实现自身定义的
成员变量的初始化。
对于这个问题,可能有的人会产生一个疑问:如果我采用多文件结构(类声明放在.hpp文件中,类定义放在.cpp文件中),派生类的构造函数我该怎么声明呢?其实构造函数的声明是不用变的,例如上面SavingAccount派生类的构造函数声明依旧为:
SavingAccount(double ba, double ite);
到此第一个问题已经解决了,看下一问题:
2.Const 成员的意义
const 函数定义更多的是工程上的意义,对程序的效率本身影响不大,由于const成员调用const成员函数,所以说
在一些“一些成员函数修改对象,一下成员函数不修改对象”“非常量成员函数不能被常量成员对象调用,因为它可能企图修改常量的数据成员”诸如此类的问题,我们用const来解决,即对于不修改成员变量的方法我们用const标示一下。
3.如何在派生类成员函数中调用基类的成员函数?
对于 非重名方法,直接调用即可,重名方法加 名词空间Account::credit()即可。
例如基类Account中的getBalance()方法,在派生类SavingAccount的方法calculate_Interest()调用方式为:
double SavingAccount::calculate_Interest()
{
return (getBalance()*interestrate)/100.0;
}
直接调用了getBalance()。
三个问题已经解决完毕,接下来让我们来看一个比较完整的例子:
创建一个银行账户的继承层次,表示银行的所有客户的账户,所有的客户都能在该银行的账户中存钱、取钱。账户也可以分成更为具体的类型,例如,存款账户SavingAccount依靠存款产生利息,支票账户CheckingAccount对每笔交易(存款或者取款)收取手续费。具体要求操作如下:
1. 创建一个类层次结构,Account为基类,派生类为SavingAccount(存款账户)和CheckingAccount(支票账户)。
2. 基类Account要求包括如下:表示账户余额的数据成员balance。3个成员函数分别是向当前余额加钱的credit,从当前账户取钱的debit,查询当前账户余额的getBalance。
3. 基类成员函数功能要求:除了完成基本功能(不再赘述)外,还需在取钱函数中实现如何保证账户不被透支,当所取金额大于账户金额时函数将保持balance不变,并给出“debit amount exceeded account balance”反馈。
4. 派生类SavingAccount要求:继承基类Account的功能,提供一个附加的数据成员interestrate返回账户的比率(利息百分比);构造函数接受初始余额值和初始利率值;另外提供一个public的成员函数calculate Interest,用来返回利息的数值,即balance 与 interestrate 的乘积。
5. 派生类CheckingAccount要求:继承基类Account 的功能,提供一个附加的数据成员表示每一笔交易的手续费用;构造函数接受初始余额值和交易费用值;重新定义成员函数credit 和 debit ,每笔交易完成后,从账户余额中减去交易的手续费用;重新定义这些函数时应使用基类的函数来更新账户余额;当debit函数成功被使用(即提款成功)才收取手续费用。(提示:定义Account的debit函数时返回一个bool型值表示是否成功提取,用返回值判断是否收取手续费。当存款或者取款后的余额低于手续费则放弃本次交易并打印“Transaction fee exceeded account balance while debiting/crediting ”)
6. 严格按照要求定义上述成员变量和成员函数,所有成员变量定义为private。
定义完成后编写主程序,能够生成不同的账户对象,调用成员函数完成相应的功能。
下面是 完整的实现程序:
//Account_ex.hpp 基类 派生类的 声明
/*
Author By : Yumaosheng
Number : 21140211080
Date: 20141109
*/
#include <iostream>
using namespace std;
//base class
class Account
{
private:
double balance;
public:
Account(double ba);
~Account();
int credit(double cash);
int debit(double cash);
double getBalance();
int setBalance(double);
};
//the sub class
class SavingAccount : public Account
{
private:
double interestrate;
public:
SavingAccount(double ba, double ite);
~SavingAccount();
double calculate_Interest();
};
// the sub class of CheckingAccount
class CheckingAccount : public Account
{
private:
double fee;
public:
CheckingAccount(double ba,double fe);
~CheckingAccount();
int credit(double cash);
int debit(double cash);
};
//Account_ex.cpp
//对基类 派生类的 声明
下面是Main()函数,对上述类定义进行测试:
/*
Author By : Yumaosheng
Number : 21140211080
Date: 20141109
*/
#include "Account_ex.hpp"
#include <iostream>
int main(int argc, char const *argv[])
{
//generate a SavingAccount object
SavingAccount saving( 100, 3 );
// double money = saving.calculate_Interest();
// cout<<money<<endl;
CheckingAccount checking1( 100, 5 );
CheckingAccount checking2( 50, 5 );
// test the SavingAccount
cout<<"SavingAccount:"<<endl;
// debit 200 yuan
saving.debit(200);
// debit 40 yuan
saving.debit(40);
// credit 50 yuan
saving.credit(50);
// debit 49 yuan
saving.debit(49);
// debit 43 yuan
saving.debit(43);
// credit 1 yuan
saving.credit(1);
saving.setBalance(saving.calculate_Interest()+saving.getBalance());
cout<<saving.getBalance()<<endl;
// test the CheckingAccount
cout <<"Checking Account1:"<< endl;
// debit 200
checking1.debit(200);
// debit 40
checking1.debit(40);
// credit 50
checking1.credit(50);
// debit 49
checking1.debit(49);
// debit 43
checking1.debit(43);
// credit 1
checking1.credit(1);
cout<<checking1.getBalance()<<endl;
// test the checking2
cout <<"Checking Account2:"<< endl;
// debit 200
checking2.debit(200);
// debit 40
checking2.debit(40);
// credit 50
checking2.credit(50);
// debit 49
checking2.debit(49);
// debit 43
checking2.debit(43);
// credit 1
checking2.credit(1);
cout<<checking2.getBalance()<<endl;
return 0;
}
上述就是完整的例子。
(而且在网上查了好久才在字里行间寻找到答案)
1.如何定义子类的构造函数,或者说如何在子类构造函数中调用父类的构造函数来实现对成员变量的初始化。
2.Const 成员函数的意义。
3.如何在派生类成员函数中调用基类的成员函数。
4.基类的私有成员是不能被派生类直接访问的,只有通过调用基类的公有方法(对私有成员修改的方法)才能实现
对基类私有成员的访问。
下面我们逐个解决前三个问题,并在解决完问题以后给出一个完整的例子:
1.如何在子类构造函数中调用基类的构造函数。
假设我有一个基类Account和一个派生类SavingAccount,SavingAccount除了继承了Account基类的一个balance变量外,自己也有一个interestrate变量。Account基类的构造函数如下:Account::Account(double ba)
{
balance = ba;
}那么派生类调用基类构造方法来实现自己的构造方法并对成员进行初始化的定义为:
SavingAccount::SavingAccount(double ba, double inte) :Account(ba)
{
// balance = ba;
interestrate = inte;
}
利用基类的构造函数来实现对派生类从基类继承得到的成员变量的初始化,利用自己的构造函数来实现自身定义的
成员变量的初始化。
对于这个问题,可能有的人会产生一个疑问:如果我采用多文件结构(类声明放在.hpp文件中,类定义放在.cpp文件中),派生类的构造函数我该怎么声明呢?其实构造函数的声明是不用变的,例如上面SavingAccount派生类的构造函数声明依旧为:
SavingAccount(double ba, double ite);
到此第一个问题已经解决了,看下一问题:
2.Const 成员的意义
const 函数定义更多的是工程上的意义,对程序的效率本身影响不大,由于const成员调用const成员函数,所以说
在一些“一些成员函数修改对象,一下成员函数不修改对象”“非常量成员函数不能被常量成员对象调用,因为它可能企图修改常量的数据成员”诸如此类的问题,我们用const来解决,即对于不修改成员变量的方法我们用const标示一下。
3.如何在派生类成员函数中调用基类的成员函数?
对于 非重名方法,直接调用即可,重名方法加 名词空间Account::credit()即可。
例如基类Account中的getBalance()方法,在派生类SavingAccount的方法calculate_Interest()调用方式为:
double SavingAccount::calculate_Interest()
{
return (getBalance()*interestrate)/100.0;
}
直接调用了getBalance()。
三个问题已经解决完毕,接下来让我们来看一个比较完整的例子:
创建一个银行账户的继承层次,表示银行的所有客户的账户,所有的客户都能在该银行的账户中存钱、取钱。账户也可以分成更为具体的类型,例如,存款账户SavingAccount依靠存款产生利息,支票账户CheckingAccount对每笔交易(存款或者取款)收取手续费。具体要求操作如下:
1. 创建一个类层次结构,Account为基类,派生类为SavingAccount(存款账户)和CheckingAccount(支票账户)。
2. 基类Account要求包括如下:表示账户余额的数据成员balance。3个成员函数分别是向当前余额加钱的credit,从当前账户取钱的debit,查询当前账户余额的getBalance。
3. 基类成员函数功能要求:除了完成基本功能(不再赘述)外,还需在取钱函数中实现如何保证账户不被透支,当所取金额大于账户金额时函数将保持balance不变,并给出“debit amount exceeded account balance”反馈。
4. 派生类SavingAccount要求:继承基类Account的功能,提供一个附加的数据成员interestrate返回账户的比率(利息百分比);构造函数接受初始余额值和初始利率值;另外提供一个public的成员函数calculate Interest,用来返回利息的数值,即balance 与 interestrate 的乘积。
5. 派生类CheckingAccount要求:继承基类Account 的功能,提供一个附加的数据成员表示每一笔交易的手续费用;构造函数接受初始余额值和交易费用值;重新定义成员函数credit 和 debit ,每笔交易完成后,从账户余额中减去交易的手续费用;重新定义这些函数时应使用基类的函数来更新账户余额;当debit函数成功被使用(即提款成功)才收取手续费用。(提示:定义Account的debit函数时返回一个bool型值表示是否成功提取,用返回值判断是否收取手续费。当存款或者取款后的余额低于手续费则放弃本次交易并打印“Transaction fee exceeded account balance while debiting/crediting ”)
6. 严格按照要求定义上述成员变量和成员函数,所有成员变量定义为private。
定义完成后编写主程序,能够生成不同的账户对象,调用成员函数完成相应的功能。
下面是 完整的实现程序:
//Account_ex.hpp 基类 派生类的 声明
/*
Author By : Yumaosheng
Number : 21140211080
Date: 20141109
*/
#include <iostream>
using namespace std;
//base class
class Account
{
private:
double balance;
public:
Account(double ba);
~Account();
int credit(double cash);
int debit(double cash);
double getBalance();
int setBalance(double);
};
//the sub class
class SavingAccount : public Account
{
private:
double interestrate;
public:
SavingAccount(double ba, double ite);
~SavingAccount();
double calculate_Interest();
};
// the sub class of CheckingAccount
class CheckingAccount : public Account
{
private:
double fee;
public:
CheckingAccount(double ba,double fe);
~CheckingAccount();
int credit(double cash);
int debit(double cash);
};
//Account_ex.cpp
//对基类 派生类的 声明
/* Author By : Yumaosheng Number : 21140211080 Date : 20141109 */ #include <iostream> #include "Account_ex.hpp" using namespace std; //the Implementation of construction method Account::Account(double ba) { balance = ba; } //the Implementation of deconstruction method Account::~Account() { balance = 0.0; } // the Implementation of credit method // add some money to the Account int Account::credit(double cash) { // add the money to balance balance += cash; return 0; } // the Implementation of credit method // get some money from the Account int Account::debit(double cash) { //if get the more money than the balance if ((balance - cash) < 0.0) { cout<<"debit amount exceeded account balance"<<endl; return 1; }else { balance -= cash; } return 0; } // the Implementation of getBalance method // return the balance double Account::getBalance() { return balance; } // the Implementation of setBalance() method int Account::setBalance(double cash) { balance = cash; return 0; } // the Implementation of SavingAccount // the Implementation of construction method of SavingAccount //调用基类的构造函数 SavingAccount::SavingAccount(double ba, double inte) :Account(ba) { // balance = ba; interestrate = inte; } // the Implementation of deconstruction method of SavingAccount SavingAccount::~SavingAccount() { // balance = 0.0; interestrate = 0.0; } double SavingAccount::calculate_Interest() { //directly using the base's method getBalance() return (getBalance()*interestrate)/100.0; } // the Implementation of CheckingAccount // the Implementation of construction method of CheckingAccount // 调用基类的构造函数 CheckingAccount::CheckingAccount(double ba , double fe) : Account(ba) { // balance = ba; // cout<<getBalance()<<endl; //test the construction fee = fe; } CheckingAccount::~CheckingAccount() { // this->balance = 0.0; fee = 0.0; } // the Implementation of CheckingAccount's credit int CheckingAccount::credit(double cash) { if (!Account::credit(cash)) { if (getBalance() > fee) { // balance -= fee; Account::debit(fee); }else { // balance -= cash; Account::debit(cash); cout<<"Transaction fee exceeded account balance while crediting"<<endl; } } return 0; } // the Implementation of CheckingAccount's debit int CheckingAccount::debit(double cash) { if (! Account::debit(cash)) { if (Account::getBalance() > fee) { // balance -= fee; Account::debit(fee); }else { // balance +=cash; Account::credit(cash); cout<<"Transaction fee exceeded account balance while debiting"<<endl; } } return 0; }
下面是Main()函数,对上述类定义进行测试:
/*
Author By : Yumaosheng
Number : 21140211080
Date: 20141109
*/
#include "Account_ex.hpp"
#include <iostream>
int main(int argc, char const *argv[])
{
//generate a SavingAccount object
SavingAccount saving( 100, 3 );
// double money = saving.calculate_Interest();
// cout<<money<<endl;
CheckingAccount checking1( 100, 5 );
CheckingAccount checking2( 50, 5 );
// test the SavingAccount
cout<<"SavingAccount:"<<endl;
// debit 200 yuan
saving.debit(200);
// debit 40 yuan
saving.debit(40);
// credit 50 yuan
saving.credit(50);
// debit 49 yuan
saving.debit(49);
// debit 43 yuan
saving.debit(43);
// credit 1 yuan
saving.credit(1);
saving.setBalance(saving.calculate_Interest()+saving.getBalance());
cout<<saving.getBalance()<<endl;
// test the CheckingAccount
cout <<"Checking Account1:"<< endl;
// debit 200
checking1.debit(200);
// debit 40
checking1.debit(40);
// credit 50
checking1.credit(50);
// debit 49
checking1.debit(49);
// debit 43
checking1.debit(43);
// credit 1
checking1.credit(1);
cout<<checking1.getBalance()<<endl;
// test the checking2
cout <<"Checking Account2:"<< endl;
// debit 200
checking2.debit(200);
// debit 40
checking2.debit(40);
// credit 50
checking2.credit(50);
// debit 49
checking2.debit(49);
// debit 43
checking2.debit(43);
// credit 1
checking2.credit(1);
cout<<checking2.getBalance()<<endl;
return 0;
}
上述就是完整的例子。
相关文章推荐
- C/C++中为什么在类外利用多态基类指向派生类指针可以调用类的私有成员函数?
- [疑问]C/C++中为什么在类外利用多态基类指向派生类指针可以调用类的私有成员函数?
- C++中通过派生类调用第二基类的普通成员函数时this指针的调整
- C++调用动态库中的虚基类成员函数时总是进错函数
- c++之——派生类的同名成员和函数调用方式及构造析构顺序
- C++:派生类的默认构造函数和拷贝构造函数调用基类构造函数的机制(含程序验证)
- 关于基类构造函数调用虚函数实际调用的不是派生类的问题的原因
- C++对象布局及多态之虚成员函数如何调用
- 介绍了如何取成员函数的地址以及调用该地址:C++
- c++ 如何把this指针传入成员函数 像全局函数一样调用成员函数
- 【C++】基类和派生类构造函数的调用顺序
- C++继承类和基类之间成员函数和虚函数调用机制
- C++派生类与基类构造函数调用次序
- 如何指定在创建派生类实例时调用的基类构造函数
- !!!!!!!!!!!!!!!!C++:派生类中重定义基类的成员函数与虚函数区别在哪里?
- C++中基类,派生类 类成员对象的构造函数,析构函数的顺序
- C++派生类函数调用基类的函数
- 多态继承情况下,有一个基类指针指向派生类对象,如何用它调用基类的虚函数?
- C++继承类和基类之间成员函数和虚函数调用机制
- c++ 基类已经存在virtual修饰的同名成员函数,派生类加不加无所谓,都是virtual的