15.5 节练习

练习 15.18:假设给定了第543页和第544页的类。同时已知每个对象的类型如注释所示,判断下面的哪些赋值语句是合法的。
解释那些不合法的语句为什么不被允许:

Base *p = &d1;      //d1的类型是 Pub_Derv
p = &d2;            //d2的类型是 Priv_Derv
p = &d3;            //d3的类型是 Prot_Derv
p = &dd1;           //dd1的类型是 Derived_from_Public
p = &dd2;           //dd2的类型是 Derived_from_Private
p = &dd3;           //dd3的类型是 Derived_from_Protected

只有 d1 和 dd1 才能够赋值。因为当派生类公有地继承基类时,用户代码才能使用派生类向基类的转换,也就是说,如果派生类继承基类的方式是受保护的或者私有的,则用户代码不能使用该转换。

题中 d1 和 dd1 类是公有的继承基类,故只有它们才能完成向基类的转换。

练习 15.19:假设 543 页和 544 页的每个类都有如下形式的成员函数:

void memfcn(Base &b) { b = *this; }

对于每个类,分别判断上面的函数是否合法。

Derived_from_Private : private Priv_Derv 这个函数不合适。

原因如下:

  1. 无论派生类以什么方式继承基类,派生类的成员函数和友元都能使用派生类向基类的转换。派生类向其直接基类的类型转换对于派生类的成员和函数来说永远是可访问的。

  2. 如果派生类继承基类的方式是公有的或受保护的,则派生类的成员和友元可以使用派生类向基类的类型转换。反之,如果派生类继承基类的方式是私有的,则不能使用。

练习 15.20:编写代码检验你对前面两题的回答是否正确。

#inclued < iostream>
using namespace std;
class Base
{
public:
    void pub_mem();

protected:
    int prot_mem;

private:
    char priv_mem;
};

struct Pub_Derv : public Base
{
    int f() { return prot_mem; }
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Pub_Derv" << endl;
    }
};

struct Priv_Derv : private Base
{
    int f1() const { return prot_mem; }
    voud memfcn(Base &b)
    {
        b = *this;
        cout << "Priv_Derv" << endl;
    }
};

struct Prot_Derv : protected Base
{
    int f2() { return prot_mem; }
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Prot_Derv" << endl;
    }
};

struct Derived_from_Public : public Pub_Derv
{
    int use_base()
    {
        return prot_mem;
    }
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Derived_from_Public" << endl;
    }
};

struct Derived_from_Protected : protected Prot_Derv
{
    int use_base()
    {
        return prot_mem;
    }
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Derived_from_Protected" << endl;
    }
};

int main()
{
    Pub_Derv d1;
    Priv_Derv d2;
    Prot_Derv d3;
    Derived_from_Public dd1;
    //Derived_from_Private dd2
    Derived_from_Protected dd3;
    Base base;
    Base *p = new Base;
    p = &d1; //d1的类型是 Pub_Derv
    //p = &d2;  //d2的类型是 Priv_Derv
    //p = &d3;  //d3的类型是 Prot_Derv
    p = &dd1; //dd1的类型是 Derived_from_Public
    //p = &dd2; //dd2的类型是 Derived_from_Private
    //p = &dd3; //dd3的类型是 Derived_from_Protected

    d1.memfcn(base);
    d2.memfcn(base);
    d3.memfcn(base);
    dd1.memfcn(base);
    //dd2.memfcn(base);
    dd3.memfcn(base);
    return 0;
}

运行结果:

Pub_Derv
Priv_Derv
Prot_Derv
Derived_from_Public
Derived_from_Protected

练习 15.21:从下面这些一般性抽象概念中任选一个(或者选一个你自己的),将其对应的一组类型组织成一个继承体系:
a 图形文件格式(如 gif、tiff、jpeg、bmp)
b 图形基元(如方格、圆、球、圆锥)
c C++语言中的类型(如类、函数、成员函数)

b 中几何图元组织成一个继承层次:

  1. 公共基类 Figure表示几何图元。
  2. 类 Rectangle、Circle、Sphere 和 Cone 分别表示矩形、圆、球形和锥形等图元,这些类可定义为 Figure 类的派生类。

练习 15.22:对于你在上一题中选择的类,为其添加合适的虚函数及公有成员和受保护的成员。

class Figure
{
public:
    Figure(double, double);

protected:
    double xSize, ySize; //图元尺寸
}

class Figure_2D : public Figure
{
public:
    Figure_2D(double, double);
    virtual double area() = 0;      //求面积操作:纯虚函数
    virtual double pcrimeter() = 0; //求周长操作:纯虚函数
}

class Figure_3D : public Figure
{
public:
    Figure_3D(double, double, double);
    virtual double cubage() = 0;

protected:
    double zSize;
}

class Rectangle : public Figure_2D
{
public:
    Rectangle(double, double);
    virtual double area();
    virtual double pcrimeter();
}

class Circle : public Figure_2D
{
public:
    Circle(double, double);
    virtual double area();
    virtual double pcrimeter();
}

class Sphere : public Figure_3D
{
public:
    Sphere(double, double, double);
    virtual double cubage();
}

class Cone : public Figure_3D
{
public:
    Cone(double, double, double);
    virtual double cubage();
}
posted @ 2020-07-30 22:31  CodeWithMe  阅读(129)  评论(0)    收藏  举报