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(){}};


0 0
原创粉丝点击