谨以本文记录派生类成员函数修改基类成员函数的方法。
现有商品类描述如下:
class CGoods { string m_name; //商品名称 double m_price; //商品价格 public: CGoods(string name,double price) //构造函数 { m_name=name; m_price=price; } string getName() const //获取商品名称 { return m_name; } double getPrice() const //获取商品价格 { return m_price; } void setPrice(double price) //设置商品价格 { m_price=price; } };
请以该类为基类进行公有派生,产生新类CBook用于描述书籍,书籍类CBook在具有名称和价格的基础上,还需要添加两个私有成员用于描述作者和书籍的页数,两个成员定义代码如下:
string m_writer; int m_pages;
请为CBook类添加一个唯一的构造函数,该函数通过四个形式参数对书籍的四个成员分别进行初始化。
请为CBook类添加前置--和后置--运算符重载,--运算符用于将价格大于10元书籍对象的价格减去1元,如果当前书籍对象的价格小于等于10元,则价格保持不变。
请为CBook重载<<运算符,使得用户可以通过cout<<按照下图格式输出一个书籍对象的数据。
程序业务流程
请编写程序从下载的数据文件中读取出数据并生成CBook类的对象,将这些对象存储到vector对象myVect中,并按照上图的格式显示这些书籍信息,然后对页码大于200页的书籍执行前置--,其余书籍执行后置--后赋值到的vector对象myVectNew中,将myVectNew中的书籍再次输出在屏幕上,然后把myVectNew对象中价格小于等于10元的书籍名称一行一个地输出在显示器上。
main函数代码如下:
void main() { vector<CBook> myVect; //创建向量 readData("d:\\books.txt",myVect); //从文件中读取数据到向量 showData(myVect); //显示读取到的数据 vector<CBook> myVectNew; //创建向量 processData(myVectNew,myVect); //对页码大于200页的书籍执行前置--, //同时把该对象插入到myVectNew中 //其余书籍执行后置--, //同时把该对象插入到myVectNew中 showData(myVectNew); outputData(myVectNew); //输出myVectNew中所有价格低于10元 //的书籍名称,一行一个 }
请根据main函数的代码,实现其中需要的函数,并进行测试。
以下是答案代码。
//author CN.TTDragon #include <iostream> #include <iomanip> #include <fstream> #include <vector> #include <iterator> #include <sstream> #include <algorithm> #include<string> #include<cmath> #include<cstdio> typedef long long ll; const ll mod=1e9+7; const ll maxn=1e5+7; const double pi=acos(-1); using namespace std; class CGoods { private: string m_name; //商品名称 double m_price; //商品价格 public: CGoods(string name,double price) //构造函数 { m_name=name; m_price=price; } string getName() const //获取商品名称 { return m_name; } double getPrice() const //获取商品价格 { return m_price; } void setPrice(double price) //设置商品价格 { m_price=price; } CGoods & operator --() { if(m_price>10) { m_price-=1; } return *this; } }; class CBook : public CGoods { private: string m_writer; int m_pages; public: CBook(string name,double price,string writer,int pages):CGoods(name,price) { m_writer=writer; m_pages=pages; } //问题在这里,不清楚如果去修改m_price的值 friend CBook & operator --(CBook & a)//这里是这题的难点,解释在文章末尾 { //1、先调用从基类继承的成员函数获取商品价格 if(a.getPrice()>10) { a.setPrice(a.getPrice()-1); } //2、根据条件,如果需要修改商品价格,则调用从基类继承的 // 成员函数重新设置商品价格为新价格 //a.m_price-=1; return a; } friend CBook operator --(CBook & a,int b)//这里是这题的难点,解释在文章末尾 { CBook temp(a); if(a.getPrice()>10) { a.setPrice(a.getPrice()-1); } return temp; } friend ostream& operator<<(ostream& o, const CBook& obj) { o<<"书名:"<<obj.getName()<<endl <<"价格:"<<obj.getPrice()<<endl <<"作者:"<<obj.m_writer<<endl <<"页数:"<<obj.m_pages<<endl <<"======"<<endl; return o; } int getpages() { return m_pages; } }; void readData(string filename,vector<CBook> & myVect) { ifstream in(filename.c_str()); string name; double price; string writer; int pages; while(in>>name>>price>>writer>>pages) { CBook a(name,price,writer,pages); myVect.push_back(a); } } void showData(vector<CBook> &myVect) { for(size_t i=0;i<myVect.size();i++) { cout<<myVect[i]; } } void outputData(vector<CBook> &myVectNew) { for(size_t i=0;i<myVectNew.size();i++) { if(myVectNew[i].getPrice()<10) { cout<<myVectNew[i].getName()<<endl; } } } void processData(vector<CBook> & myVectNew,vector<CBook> & myVect) { for (size_t i=0;i<myVect.size();i++) { if(myVect[i].getpages()>200) { --myVect[i]; myVectNew.push_back(myVect[i]); } } } int main() { vector<CBook> myVect; //创建向量 readData("f:\\C++\\homework\\2013-3\\books.txt",myVect); //从文件中读取数据到向量 showData(myVect); //显示读取到的数据 vector<CBook> myVectNew; //创建向量 processData(myVectNew,myVect); //对页码大于200页的书籍执行前置--, //同时把该对象插入到myVectNew中 //其余书籍执行后置--, //同时把该对象插入到myVectNew中 showData(myVectNew); outputData(myVectNew); //输出myVectNew中所有价格低于10元 //的书籍名称,一行一个 return 0; }
写在最后:
这题本身是一个有手就能写的题(事实证明我没手),但是它有一个难点,那就是派生类的自减函数,你肯定是无法通过派生类的函数去对基类的私有成员进行操作,我们都知道类的私有成员只能通过自己的成员函数来操纵,那么这里的修改方式就是在派生类中调用基类的两个成员函数来帮助我们去实现这个功能,而不是和以前那样直接减。