您的位置:首页 > 编程语言 > C语言/C++

c++primer(第五版) 第十五章 面向对象程序设计习题答案

2016-04-14 11:56 831 查看
纯原创    转载请注明出处:http://blog.csdn.net/axuan_k

略过书上有现成代码的题目

15.1  15.2

15.1
虚成员是基类中的概念
基类中的某些函数希望它的派生类能够重新定义自己的版本
则基类中这样的函数被称为虚函数(虚成员)

15.2
private的成员:只有本类的对象或友元函数或友元类的对象能调用它
protected的成员:除上述之外,本类的派生类的对象也能调用它


15.4

#include<iostream>
using namespace std;
//    15.4
class Base{};
class b1:public b1{};         //不能继承自己
class b2:private Base{};      //这是一个派生类的定义语句而不是声明语句
class b3:public Base{} ;      //派生类的声明应与普通类的声明一样,不该有列表
int main(){
return 0;
}


15.8   15.9  15.10
#include<iostream>
using namespace std;
int main(){
//    15.8
//    静态类型的成员在进行编译的时候就知道它的类型了
//    动态类型的成员直到程序运行时才直到它自己的类型

//    15.9
//    基类对象的指针指向子类对象
//    基类对象的引用引用子类对象

//    15.10
//    read()函数的第一个参数虽然是istream类型的引用
//    但input对象是istream子类ifstream的对象,
//    即这个参数是动态类型的,所有可以正常工作
return 0;
}


 

15.12       15.13   15.14

#include<iostream>
#include<string>
using namespace std;
class base
{
public:
string name() { return basename; }
virtual void print(ostream &os) { os << basename<<endl; }
private:
string basename="sssss";
};

class derived : public base
{
public:
void print(ostream &os) override { base::print(os); //改成这样
os << "  " << i<<endl;
}
private:
int i=2;
};

int main(){
//    15.12
//    有必要,因为override和final的定义并不矛盾
//    override是覆盖基类同名的函数成员
//    而final则表示该函数成员不能继续继承下去
//    可以并且有必要存在两点都满足的成员函数

//    15.13
//    会产生无限递归,在派生类derived中paint方法会重复调用自己
//    从而产生递归,应该通过使用作用域运算符强迫调用基类的paint函数
//    即应改为:
//    Base::paint(os);
derived a;
a.print(cout);
cout<<endl;

//    15.14
base bobj;
base *bp1=&bobj;
base &br1=bobj;

derived dobj;
base *bp2=&dobj;
base &br2=dobj;

bobj.print(cout);
//调用base::paint
dobj.print(cout);
//调用derived::paint
cout<<bp1->name()<<endl;
//父类对象bobj的name
cout<<bp2->name()<<endl;
//子类对象dobj继承来的name
br1.print(cout);
//调用base::paint
br2.print(cout);
//调用derived::paint
return 0;
}


15.15  15.16  15.17

#include<iostream>
#include<string>
using namespace std;
//  15.15
class Quote{
public:
Quote()=default;
Quote(const string& book,double p):bookNo(book),price(p){}
string isbn()const{return bookNo;}
virtual double net_price(size_t n)const{
return n*price;
}
private:
string bookNo;
protected:
double price=0.0;
};

class Disc_quote:public Quote{
public:
Disc_quote()=default;
Disc_quote(const string& name,double p,size_t qty,double disc):Quote(name,p),quantity(qty),discount(disc){}
double net_price(size_t)const =0;
protected:
size_t quantity=0;
double discount=0.0;
};

class Bulk_quote:public Disc_quote{
public:
Bulk_quote()=default;
Bulk_quote(const string& name,double p,size_t qty,double disc):Disc_quote(name,p,qty,disc){}
//    15.16
double net_price(size_t cnt)const override{
if(cnt>=quantity)
return cnt*(1-discount)*price;
else
return cnt*price;
}

};
int main(){
//    15.17
Quote a("asdsad",1.2);
Disc_quote b("sasda",1.2,123,2.2);
//D:\3.22\asd.cpp|45|error: cannot declare variable 'b' to be of abstract type 'Disc_quote'|
Bulk_quote c("sasda",1.2,123,2.2);
return 0;
}


15.18  15.19

#include <iostream>
#include<string>
#include<sstream>
using namespace std;

int main() {

//    15.18
Base *p = &d1; //legal
p = &d2; //illegal
p = &d3; //illegal
p = &dd1; //legal
p = &dd2; //illegal
p = &dd3; //illegal
//只有第一个和第四个是正确的 这里是 在用户代码中 派生类向基类的转换(指针)
//书中原话:只有当D公有的继承B时,用户代码  才能使用派生类向基类转换

//    15.19
//    因为转换发生在函数中,所有这里用到书中第二条规则:不论D以什么方式继承B,D
//    的成员函数和友元都能使用派生类向基类的转换
//    所以所有继承于Base的类Pub_Derv,Priv_Derv,Prot_Derv都可以转换
//    Derived_from_Public ,Derived_from_Protected 这两个类也可以转换两次得到
return 0;
}


15.23

#include <iostream>
#include <string>
class Base
{
public:
virtual int fcn(){ std::cout << "Base::fcn()\n"; return 0; }
};

class D1 : public Base
{
public:
//去掉参数列表中的int 同时可在()后面添加override
int fcn() override  { std::cout << "D1::fcn()\n";return 0; }
virtual void f2() { std::cout << "D1::f2()\n"; }
};

class D2 : public D1
{
public:
int fcn(int);
int fcn() override { std::cout << "D2::fcn()\n";return 0; }
void f2() override { std::cout << "D2::f2()\n"; }
};

int main()
{
Base bobj;
D1 d1obj;
D2 d2obj;

Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
bp1->fcn(); //Base::fcn()
bp2->fcn(); // D1::fcn()
bp3->fcn(); //  D2::fcn()

D1 *d1p = &d1obj; D2 *d2p = &d2obj;

//bp2->f2();     //同书上 Base没有f2()
//d1p->f2();    // D1::f2()
//d2p->f2();    // D2::f2()

return 0;
}


15.24

基类需要虚析构函数
在这些类完成动态绑定的同时,通过调用正确的析构函数来执行正确的销毁操作


15.25

会产生编译错误
因为Bulk_quote中也有默认构造函数,而这个构造函数的状态是由Disc_quote的默认构造函数决定的;
Bulk_quote删除了默认构造函数,同时存在另一个4个参数的构造函数,所以编译器也不会再合成默认构造函数


 15.26

#include<iostream>
#include<string>
using namespace std;
//  15.15
class Quote{
public:
Quote(){cout<<"Quote()"<<endl;};
Quote(const string& book,double p):bookNo(book),price(p){
cout<<"Quote(const string& book,double p)"<<endl;
}
Quote(const Quote& q):bookNo(q.bookNo),price(q.price){
cout<<"Quote(const Quote& q)"<<endl;
}
Quote& operator=(const Quote& q){
cout<<"Quote& operator=(const Quote& q)"<<endl;
bookNo=q.bookNo;
price=q.price;
return *this;
}
virtual ~Quote(){cout<<"virtual ~Quote()"<<endl;}
string isbn()const{return bookNo;}
virtual double net_price(size_t n)const{
return n*price;
}
private:
string bookNo;
protected:
double price=0.0;
};

class Disc_quote:public Quote{
public:
Disc_quote()=default;
Disc_quote(const string& name,double p,size_t qty,double disc):Quote(name,p),quantity(qty),discount(disc){}
Disc_quote(const Disc_quote& dq):Quote(dq),quantity(dq.quantity),discount(dq.discount){}
Disc_quote& operator=(const Disc_quote& dq){
Quote::operator=(dq);
quantity=dq.quantity;
discount=dq.discount;
return *this;
}
double net_price(size_t)const =0;
protected:
size_t quantity=0;
double discount=0.0;
};

class Bulk_quote:public Disc_quote{
public:
Bulk_quote(){cout<<"Bulk_quote()"<<endl;};
Bulk_quote(const string& name,double p,size_t qty,double disc):Disc_quote(name,p,qty,disc){
cout<<"Bulk_quote(const string& name,double p,size_t qty,double disc)"<<endl;
}
Bulk_quote(const Bulk_quote& bq):Disc_quote(bq){
cout<<"Bulk_quote(const Bulk_quote& bq)"<<endl;
}
Bulk_quote& operator=(const Bulk_quote& bq){
cout<<"Bulk_quote& operator=(const Bulk_quote& bq)"<<endl;
Disc_quote::operator=(bq);
return *this;
}
~Bulk_quote()override{
cout<<"~Bulk_quote()"<<endl;
}
double net_price(size_t cnt)const override{
if(cnt>=quantity)
return cnt*(1-discount)*price;
else
return cnt*price;
}

};
int main(){
//    15.17    Quote a("asdsad",1.2);

Bulk_quote c("sasda",1.2,123,2.2);
cout<<endl<<endl;
Bulk_quote d(c);
cout<<endl<<endl;
c=d;
cout<<endl<<endl;
return 0;
}


15.27

上题加上using声明即可


15.28  15.29

#include<iostream>
#include<vector>
#include<memory>
#include"Bulk_quote.h"
using namespace std;
int main(){
double ans1=0.0,ans2=0.0;
vector<Quote>vec1;
vector<shared_ptr<Quote> >vec2;

vec1.push_back(Quote("11111-1",3.3));
vec1.push_back(Bulk_quote("2222-2",3.3,2,0.5));

vec2.push_back(make_shared<Quote>("11111-1",3.3));
vec2.push_back(make_shared<Bulk_quote>("2222-2",3.3,2,0.5));
for(int i=0;i<vec1.size();i++){
ans1+=vec1[i].net_price(2);
ans2+=vec2[i]->net_price(2);
}
cout<<ans1<<" "<<ans2<<endl;
//13.2    9.9
//答案不一样 因为vec1保存的全部是Quote的对象(静态类型) 也就是说Bulk_quote强行转换成了Quote
//而vec2保存的是(动态类型) 转换的仅是指针
return 0;
}


15.31  15.32   15.33

15.31
(a) OrQuery, AndQuery, NotQuery, WordQuery
(b) OrQuery, AndQuery, NotQuery, WordQuery
(c) OrQuery, AndQuery, WordQuery

15.32
拷贝,移动,赋值和销毁使用的都是编译器自动合成的版本

拷贝,赋值:新对象的智能指针q将指向原对象中q指向的Query_base体系下的对象
所以成员智能指针的use count +1

移动:原对象的q(智能指针)指向空nullptr,新对象指向原对象中成员q(智能指针)指向的对象
use count不变

销毁:对象成员q(智能指针)的use count -1,如果use count为0
则它指向的对象就会自动销毁

15.33
Query_base是一个纯虚类,没有自己的对象


15.34

15.34
(a)
WordQuery    三次   "fiery","bird" and "wind"
Query        三次   "fiery","bird" and "wind"

AndQuery     一次
BinaryQuery  一次
Query        一次   &运算结果

OrQuery      一次
BinaryQuery  一次
Query        一次   |运算结果

(b)
BinaryQuery
BinaryQuery
Query
WordQuery
Query
WordQuery
Query
WordQuery

(c)
Query::eval()
Query_base的派生类的各种eval


15.35

Query.h

#ifndef QUERY
#define QUERY

#include<string>
#include<memory>
#include"Query_base.h"
#include"WordQuery.h"
#include"QueryResult.h"
using namespace std;
class Query{
friend operator|(const Query& l,const Query& r);
friend operator&(const Query& l,const Query& r);
friend operator~(const Query& obj);
public:
Query(const string& str):q(new WordQuery(str)){}
QueryResult eval(const TextQuery& tq)const{
return q->eval(tq);
}
string rep()const{
return q->rep();
}
private:
shared_ptr<Query_base>q;
};

#endif // QUERY


Query_base.h

#ifndef QUERY_BASE
#define QUERY_BASE

#include<string>
#include"QueryResult.h"
using namespace std;
class Query_base{
public:
virtual QueryResult eval(const TextQuery&)const=0;
virtual string rep()const =0;
virtual ~Query_base(){};
};

#endif // QUERY_BASE


15.38

BinaryQuery a = Query("fiery") & Query("bird");
//不合法   纯虚类没有对象
AndQuery b = Query("fiery") & Query("bird");
//不合法   &操作后返回的是Query的对象  无法转换为AndQuery的对象
OrQuery c = Query("fiery") & Query("bird");
//不合法   &操作后返回的是Query的对象  无法转换为OrQuery的对象


15.42

不会发生任何意外
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: