《C++ Primer》第15章 面向对象程序设计
15.5节 访问控制与继承 习题答案
练习15.18:假设给定了第543页和第544页的类,同时已知每个对象的类型如注释所示,判断下面的哪些赋值语句是合法的。解释那些不合法的语句为什么不被允许:
Base *p = &dl; //d1的类型是Pub_Derv
p = &d2; //d2的类型是Priv_Derv
p = &d3; //d2的类型是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:编写代码检验你对前面两题的回答是否正确。
【出题思路】
实际编程练习,判断继承运用是否掌握。
【解答】
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
class Base
{
public:
void pub_mem();
protected:
int prot_mem;
private:
char priv_mem;
};
class Pub_Derv: public Base
{
public:
int f()
{
return prot_mem;
}
void memfcn(Base &b)
{
b = *this;
cout << "Pub_Derv=====================" << endl;
}
};
class Priv_Derv: private Base
{
public:
int f1() const
{
return prot_mem;
}
void memfcn(Base &b)
{
b = *this;
cout << "Priv_Derv==================" << endl;
}
};
class Prot_Derv: protected Base
{
public:
int f2()
{
return prot_mem;
}
void memfcn(Base &b)
{
b = *this;
cout << "Prot_Derv==================" << endl;
}
};
class Derived_from_Public: public Pub_Derv
{
public:
int use_base()
{
return prot_mem;
}
void memfcn(Base &b)
{
b = *this;
cout << "Derived_from_Public==================" << endl;
}
};
class Derived_from_Protected: protected Prot_Derv
{
public:
int use_base()
{
return prot_mem;
}
void memfcn(Base &b)
{
b = *this;
cout << "Derived_from_Protected==================" << endl;
}
};
//class Derived_from_Private: private Priv_Derv
//{
//public:
// int use_base()
// {
// return priv_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);
std::cout << "Hello, World!\n";
return 0;
}
运行结果:
练习15.21:从下面这些一般性抽象概念中任选一个(或者选一个你自己的),将其对应的一组类型组织成一个继承体系:
(a)图像文件格式(如 gif、 tiff、 jpeg、 bmp )
(b)几何图元(如矩形、圆、球形、锥形)
(c)C++语言的类型(如类、函数、成员函数)
【出题思路】
练习继承层次构造。
【解答】
对(b)中的几何图元组织成一个继承层次:1)公共基类Figure,表示几何图元;2)类Rectangle、Circle、Sphere和Cone分别表示矩形、圆、球形和锥形等图元,这些类可定义为Figure类的派生类。
练习15.22:对于你在上一题中选择的类,为其添加合适的虚函数及公有成员和受保护的成员。【出题思路】
类构造练习。
【解答】
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
class Figure
{
public:
Figure(double x, double y)
:xSize(x), ySize(y)
{
}
double getXSize()
{
return xSize;
}
double getYSize()
{
return ySize;
}
protected:
double xSize, ySize;//图元的尺寸
};
class Figure_2D: public Figure
{
public:
Figure_2D(double x, double y)
:Figure(x, y)
{
}
virtual double area() = 0;//求面积操作,纯虚函数
virtual double perimeter() = 0;//求周长操作,纯虚函数
};
class Figure_3D: public Figure
{
public:
Figure_3D(double x, double y, double z)
:Figure(x, y), zSize(z)
{
}
double getZSize()
{
return zSize;
}
virtual double cubage() = 0;
protected:
double zSize;
};
class Rectangle: public Figure_2D
{
public:
Rectangle(double x, double y)
:Figure_2D(x, y)
{
}
virtual double area()
{
double dArea = getXSize() * getYSize();
cout << "Rectangle area============" << dArea << endl;
return dArea;
}
virtual double perimeter()
{
double dPerimeter = 2 * (getXSize() + getYSize());
cout << "Rectangle perimeter============" << dPerimeter << endl;
return dPerimeter;
}
};
class Circle: public Figure_2D
{
public:
Circle(double x, double y)
:Figure_2D(x, y)
{
}
virtual double area()
{
double dArea = getXSize() * getYSize();
cout << "Circle area============" << dArea << endl;
return dArea;
}
virtual double perimeter()
{
double dPerimeter = 2 * (getXSize() + getYSize());
cout << "Circle perimeter============" << dPerimeter << endl;
return dPerimeter;
}
};
class Sphere: public Figure_3D
{
public:
Sphere(double x, double y, double z)
:Figure_3D(x, y, y)
{
}
virtual double cubage()
{
double dCubage = getXSize() * getYSize() * getZSize();
cout << "Sphere cubage============" << dCubage << endl;
return dCubage;
}
};
class Cone: public Figure_3D
{
public:
Cone(double x, double y, double z)
:Figure_3D(x, y, y)
{
}
virtual double cubage()
{
double dCubage = getXSize() * getYSize() * getZSize();
cout << "Cone cubage============" << dCubage << endl;
return dCubage;
}};
int main()
{
Rectangle *rect = new Rectangle(20, 10);
rect->area();
rect->perimeter();
Circle circle(15, 20);
circle.area();
circle.perimeter();
Sphere *sphere = new Sphere(2, 3, 4);
sphere->cubage();
Cone cone(5, 6, 7);
cone.cubage();
std::cout << "Hello, World!\n";
return 0;
}
运行结果: