18.3节练习
来源:互联网 发布:小米笔记本15.6 知乎 编辑:程序博客网 时间:2024/06/05 18:37
练习18.21 解释下列声明的含义,在它们当中存在错误吗?如果有,请指出来并说明错误的原因。
(a) class CADVehicle : public CAD, Vehicle{...} //无错误,私有继承Vehicle
(b) class DblList : public List, public List{...} //一个基类只能继承一次
(c) class iostream : public istream, public ostream{...} //无错误
练习18.22 已知存在如下所示的类的继承体系,其中每个类都定义了一个默认构造函数:
class A{...};class B :public A { ... };class C :public B { ... };class X { ... };class Y { ... };class Z :public X, public Y { ... };class MI :public C, public Z { ... };对于下面的定义来说,构造函数的执行顺序是怎样的?
MI mi;
A-B-C-X-Y-Z-MI
练习18.23 使用练习18.22的继承体系以及下面定义的类D,同时假定每个类都定义了默认构造函数,请问下面的哪些类型转换是不被允许的?
class D : public X, public C{...};
D* pd = new D;
(a) X* px = pd; t
(b) A* pa = pd; t
(c) B* pb = pd; t
(d) C* pc = pd; t
练习18.24 在第714页,我们使用一个指向Panda对象的Bear指针进行了一系列调用,假设我们使用的是一个指向Panda对象ZooAnimal指针将发生什么情况,对这些调用语句逐一说明。
ZooAnimal* pz = new Panda("panda");
pz->print(); //正确,调用Panda::print();
pz->cuddle(); //正确,调用Panda::cuddle();
pz->highlight(); //错误,不属于ZooAnimal的接口
delete pz; //正确,调用Panda::~Panda()
练习18.25 假设我们两个基类Base1和Base2,它们各自定义了一个名为print的虚成员和一个虚析构函数。从这两个基类中派生出下面的类,它们都重新定义了print函数:
class D1 : public Base1 {...};
class D2 : public Base2 {...};
class MI : public public D1, publuc D2 {...};
通过下面的指针,指出在每个调用中分别使用了哪个函数:
Base1* pb1 = new MI;
Base2 *pb2 = new MI;
D1* pd1 = new MI;
D2* pd2 = new MI;
(a) pb1->print(); //MI::print()
(b) pd1->print(); //MI::print()
(c) pd2->print(); //MI::print()
(d) delete pb2; //MI::~MI() , D2::~D2(), Base2::~Base2(), D1::~D1(), Base1::~Base1()
(e) delete pd1; //如上
(f) delete pd2; //如上
测试程序:
#include <iostream>#include <string>#include <memory>using namespace std;class Base1 {public:virtual void print() { cout << "Base1 print()" << endl; }virtual ~Base1() { cout << "Base1 ~" << endl; }};class Base2 {public:virtual void print() { cout << "Base2 print()" << endl; }virtual ~Base2() { cout << "Base2 ~" << endl; }};class D1:public Base1 {public:virtual void print() { cout << "D1 print()" << endl; }virtual ~D1() { cout << "D1 ~" << endl; }};class D2 :public Base2 {public:virtual void print() { cout << "D2 print()" << endl; }virtual ~D2() { cout << "D2 ~" << endl; }};class MI :public D1,public D2 {public:virtual void print() { cout << "MI print()" << endl; }virtual ~MI() { cout << "MI ~" << endl; }};int main(){Base1* pb1 = new MI;Base2* pb2 = new MI;D1* pd1 = new MI;D2* pd2 = new MI;pb1->print();pd1->print();pd2->print();//delete pb2;//delete pd1;delete pd2;}
#include <iostream>#include <string>#include <vector>using namespace std;struct Base1 {void print(int) const { cout << "Base1 print(int) const" << endl; }protected:int ival;double dval;char cval;private:int* id;};struct Base2 {void print(double) const { cout << "Base2 print(double) cont" << endl; }protected:double fval;private:double dval;};struct Derived :public Base1 {void print(std::string) const { cout << "Derived print(string) const" << endl; }protected:std::string sval;double dval;};struct MI :public Derived, public Base2 {void print(std::vector<double>) { cout << "MI print(vector<int>)" << endl; }protected:int* val;std::vector<double> dvec;};
练习18.26 已知如上所示的继承体系,下面对print的调用为什么是错误的?适当修改MI,令其对print的调用可以编译通过并正确执行。
MI mi;
mi.print(42); //无法从vector<double>向int的转换。
void print(int) { cout << "MI print(int)" << endl; }
练习18.27 已知如上所示的继承体系,同时假定为MI添加了一个名为foo的函数:
int ival;double dval;void MI::foo(double cval){int val;//练习中的问题发生在此处}
(a) 列出在MI::foo中可见的所有名字。
foo::ival.cval
MI::ival dvec print foo
Derived::print sval dval
Base1::print ival dval cval
Base2::print fval
(b) 是否存在某个可见的名字是继承多个基类的。
ival print dval cval
(c) 将Base1的dval成员与Derived的dval成员求和后赋给dval的局部实例。
void MI::foo(double cval){int dval;dval = Base1::dval + Derived::dval; Base2::fval = MI::dvec.back();Derived::sval[0] = Base1::cval;}
(d) 将MI::dvec的最后一个元素的值赋给Base2::fval。
如上
(e) 将从Base1继承的cval赋给Derived继承的sval的第一个字符。
如上
练习18.28 已知存在如下的继承体系,在VMI类的内部哪些继承而来的成员无须前缀限定符就能直接访问?哪些必须要有限定符才能访问?说明你的原因。
#include <iostream>#include <string>using namespace std;struct Base {void bar(int) { cout << "Base bar()" << endl; }//需要限定符,否则被Derived1覆盖protected:int ival = 0;//需要访问限定符};struct Derived1 :virtual public Base {void bar(char) { cout << "Derived1 bar()" << endl; }//不需要限定符void foo(string) { cout << "Derived1 foo()" << endl; }//需要访问限定符,与Derived2的foo()产生二义性 protected:char cval = '1';//需要访问限定符,与Derived2的cval产生二义性};struct Derived2 : virtual public Base{void foo(int) { cout << "Derived2 foo()" << endl; }//需要访问限定符protected:int ival = 2;//无须访问限定符,覆盖基类的ivalchar cval = '2';//需要};class VMI:public Derived1,public Derived2{public:void use(){bar(1);bar('c');Derived1::foo("hello");Derived2::foo(1);cout << ival << endl;cout << Base::ival << endl;cout << Derived1::cval << endl;}};int main(){VMI vmi;vmi.use();}
练习18.29 已知有如下所示的类继承关系:
class Class {...};
class Base : public Class {...};
class D1 : virtual public Base {...};
class D2 : virtual public Base {...};
class MI : public D1, public D2 {...};
class Final :public MI, public Class {...};
(a) 当作用于一个Final对象时,构造函数和析构函数的执行次序分别是什么?
构造函数:Class(), Base(), D1(), D2(), MI(), Class(), Final()
析构函数:与上述次序相反。
(b) 在一个Final对象中有几个Base()部分?几个Class部分?
1个,2个
(c) 下面的那些赋值运算符将造成编译错误?
Base* pb; Class* pc; MI* pmi; D2* pd2;
(a) pb = new Class; 错误,不能将基类转换成派生类。
(b) pc = new Final; 正确
(c) pmi = pb; 错误
(d) pd2 = pmi; 正确
练习18.30 在Base中定义一个默认构造函数、一个拷贝构造函数和一个接受int形参的构造函数。在每个派生类中分别定义这三种构造函数,每个构造函数应该使用它的实参舒适化其Base部分。
#include <iostream>using namespace std;class Class {//...};class Base:public Class {public:Base() :ival(0),Class(){}Base(const Base& b) :ival(b.ival) {}Base(int val):ival(val),Class(){}protected:int ival;};class D1 :virtual public Base {public:D1() : Base() {}D1(const D1& d1) = default;D1(int val) : Base(val) {}};class D2 :virtual public Base {public:D2() :Base() {}D2(const D2& d2) = default;D2(int val) :Base(val) {}};class MI :public D1, public D2 {public:MI() :D1(), D2() {}MI(const MI& mi) = default;MI(int val) : D1(val), D2(val) {}};class Final : public MI, public Class {Final() :MI(), Class() {}Final(const Final& f) = default;Final(int val) :MI(val), Class(){}};
- 18.3节练习
- 第十八章 18.3.1节练习
- 第十八章 18.3.2节练习
- 第十八章 18.3.3节练习
- 第十八章 18.3.4节练习
- 第十八章 18.3.5节练习
- C++ Primer 练习答案 1.2节练习
- C++ Primer 练习答案 1.4节练习
- 第一章 1.1节练习
- 第一章 1.2节练习
- 第一章 1.3节练习
- 10.1节练习
- 10.2.1节练习
- 10.2.2节练习
- 10.2.3节练习
- 10.3.1节练习
- 10.3.2 节练习
- 10.3.3节练习
- Spring的代理模式(静态代理和动态代理)
- “深入理解”—交换排序算法
- L - 空心三角形 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
- 怎么提供建议 vs 硅谷创业家讲座记录
- javaWeb之json的简单使用
- 18.3节练习
- java springAMQP-1.6 rabbitmq-3.6.3
- centos7系统下安装memcache数据库
- 详解Java解析XML的四种方法
- 我的Java后端书架 (2016年暮春3.0版)
- IOS控件之UITableView使用技巧
- MyEclipse 快捷键大全
- poj 3180 The Cow Prom(奶牛舞会)
- 更新高德地图语音模块