C++程序设计(第3版)谭浩强 第12章 习题

1.在例12.1程序基础上作一些修改。声名Point(点)类, 由Point类派生出Circle(圆)类,再由Circle类派生出Cylinder(圆柱体)类。 将类的声明部分分别作为3个头文件, 对它们的成员函数的声明部分分别作为3个源文件(.cpp文件), 在主函数中用“#include”命令把它们包含进来,形成一个完整的程序,并上机运行。

【解】

//1.在例12.1程序基础上作一些修改。声名Point(点)类,
//  由Point类派生出Circle(圆)类,再由Circle类派生出Cylinder(圆柱体)类。
//  将类的声明部分分别作为3个头文件,
//  对它们的成员函数的声明部分分别作为3个源文件(.cpp文件),
//  在主函数中用“#include”命令把它们包含进来,形成一个完整的程序,并上机运行。

//point.h
#ifndef _POINT_H_
#define _POINT_H_

class Point
{
public:
	Point(float x = 0, float y = 0);
	void setPoint(float, float);
	float getX() const { return x; }
	float getY() const { return y; }
	friend ostream & operator<<(ostream &, const Point &);
	~Point();
protected:
	float x, y;
};

#endif

//point.cpp
#include <iostream>
using namespace std;
#include "point.h"

Point::Point(float a, float b) { x = a; y = b; }

void Point::setPoint(float a, float b) { x = a; y = b; }

ostream & operator<<(ostream &output, const Point &p)
{
	output << "[" << p.x << "," << p.y << "]" << endl;
	return output;
}

Point::~Point() {}

//circle.h
#ifndef _CIRCLE_H_
#define _CIRCLE_H_
#include "point.h"

class Circle :public Point
{
public:
	Circle(float x = 0, float y = 0, float r = 0);
	void setRadius(float);
	float getRadius() const;
	float area() const;
	friend ostream &operator<<(ostream &, const Circle &);
	~Circle();
protected:
	float radius;
};

#endif

//circle.cpp
#include <iostream>
using namespace std;
#include "circle.h"

Circle::Circle(float a, float b, float r) :Point(a, b), radius(r) {}

void Circle::setRadius(float r) { radius = r; }

float Circle::getRadius() const { return radius; }

float Circle::area() const { return 3.14159 * radius * radius; }

ostream &operator<<(ostream &output, const Circle &c)
{
	output << "Center = [" << c.x << "," << c.y << "], r = " << c.radius << ", area = " << c.area() << endl;
	return output;
}

Circle::~Circle() {}

//cylinder.h
#ifndef _CYLINDER_H_
#define _CYLINDER_H_
#include "circle.h"

class Cylinder :public Circle
{
public:
	Cylinder(float x = 0, float y = 0, float r = 0, float h = 0);
	void setHeight(float);
	float getHeight() const;
	float area() const;
	float volume() const;
	friend ostream& operator<<(ostream&, const Cylinder&);
	~Cylinder();
protected:
	float height;
};

#endif

//cylinder.cpp
#include <iostream>
using namespace std;
#include "cylinder.h"

Cylinder::Cylinder(float a, float b, float r, float h) :Circle(a, b, r), height(h) {}

void Cylinder::setHeight(float h) { height = h; }

float Cylinder::getHeight() const { return height; }

float Cylinder::area() const { return 2 * Circle::area() + 2 * 3.14159 * radius * height; }

float Cylinder::volume() const { return Circle::area() * height; }

ostream &operator<<(ostream &output, const Cylinder &cy)
{
	output << "Center = [" << cy.x << "," << cy.y << "], r = " << cy.radius << ", h = " << cy.height << "\narea = " << cy.area() << ", volume = " << cy.volume() << endl;
	return output;
}

Cylinder::~Cylinder() {};

//main.cpp
#include <iostream>
using namespace std;
#include "cylinder.h"

int main()
{
	Cylinder cy1(3.5, 6.4, 5.2, 10);
	cout << "original cylinder:\nx = " << cy1.getX() << ", y = " << cy1.getY() << ", r = " << cy1.getRadius() << ", h = " << cy1.getHeight() << "\narea = "
		<< cy1.area() << ", volume = " << cy1.volume() << endl;
	cy1.setHeight(15);
	cy1.setRadius(7.5);
	cy1.setPoint(5, 5);
	cout << "\nnew cylinder:\n" << cy1;
	Point &pRef = cy1;
	cout << "\npRef as a point:" << pRef;
	Circle &cRef = cy1;
	cout << "\ncRef as a Circle:" << cRef;

	return 0;
}

//original cylinder:
//x = 3.5, y = 6.4, r = 5.2, h = 10
//area = 496.623, volume = 849.486
//
//new cylinder:
//Center = [5,5], r = 7.5, h = 15
//area = 1060.29, volume = 2650.72
//
//pRef as a point:[5,5]
//
//cRef as a Circle:Center = [5,5], r = 7.5, area = 176.714

2.请比较函数重载和虚函数在概念上和使用方式有什么区别。

【解】

(1)函数重载可以用于普通函数(非成员函数)和类的成员函数,而虚函数只能用于类的成员函数。 (2)函数重载可以用于析构函数,而虚函数不能用于构造函数。 (3)如果对成员函数进行重载,则重载的函数与被重载的函数应当都是同一类中的成员函数,不能分属于不同两个不同继承层次的类。 函数重载是横向的重载。虚函数是对同一类族中的基类和派生类的同名函数的处理,即允许在派生类中对基类的成员函数重新定义。 虚函数的作用是处理纵向的同名函数。 (4)重载的函数必须具有相同的函数名,但函数的参数个数和参数类型二者中至少有一样不同,否则在编译时无法区分它们。而虚函数则 要求在同一类族中的所有虚函数不仅函数名相同,而且要求函数类型、函数的参数个数和参数类型都全部相同,否则就不是重定义了, 也就是不是虚函数了。 (5)函数重载是程序编译阶段确定操作对象的,属静态关联。虚函数是在函数运行阶段确定操作的对象的,属动态关联。

3.在例12.3的基础上作以下修改,并作必要的讨论。

(1)把构造函数修改为带参数的函数,在建立对象时初始化。

(2)先不将析构函数声明为virtual,在main函数中另设一个指向Circle类对象的指针变量,使它指向grad1运行程序,分析结果。

(3)不作第(2)点的修改而将析构函数声明为virtual,运行程序,分析结果。

【解】

//12.3
//3.在例12.3的基础上作以下修改,并作必要的讨论。
//  (1)把构造函数修改为带参数的函数,在建立对象时初始化。
//  (2)先不将析构函数声明为virtual,
//	 在main函数中另设一个指向Circle类对象的指针变量,使它指向grad1。
//	 运行程序,分析结果。
//  (3)不作第(2)点的修改而将析构函数声明为virtual,运行程序,分析结果。

#include <iostream>
using namespace std;
class Point
{
public:
	Point(float a, float b) :x(a), y(b) { }
	~Point() { cout << "executing Point destructor" << endl; }
private:
	float x;
	float y;
};
class Circle :public Point
{
public:
	Circle(int a, int b, int r) :Point(a, b), radius(r) { }
	~Circle() { cout << "executing Circle destructor" << endl; }
private:
	float radius;
};
int main()
{
	Point *p = new Circle(2.5, 1.8, 4.5);
	delete p;
	return 0;
}

//executing Point destructor

//(2)在上面的基础上将main函数改写为

int main()
{
	Point *p = new Circle(2.5, 1.8, 4.5);//定义指向基类的指针并指向新对象
	Circle *pt = new Circle(2.5, 1.8, 4.5);//定义指向派生类的指针并指向新对象
	delete pt;
	return 0;
}

//executing Circle destructor
//executing Point destructor

//(3)使用虚函数,程序如下:
#include <iostream>
using namespace std;
class Point
{
public:
	Point(float a, float b) :x(a), y(b) { }
	virtual ~Point() { cout << "executing Point destructor" << endl; }//声明为虚函数
private:
	float x;
	float y;
};
class Circle :public Point
{
public:
	Circle(float a, float b, float r) :Point(a, b), radius(r) { }
	virtual ~Circle() { cout << "executing Circle destructor" << endl; }//声明为虚函数
private:
	float radius;
};
int main()
{
	Point *p = new Circle(2.5, 1.8, 4.5);
	delete p;
	return 0;
}

//executing Circle destructor
//executing Point destructor

4.编写一个程序,声明抽象基类Shape,由它派生出3个派生类:Circle(圆形)、Rectangle(矩形)、Triangle(三角形),用一个函数printArea分别输出以上三者的面积,3个图形的数据在定义对象时给定。

【解】

//12.4
//4.编写一个程序,声明抽象基类Shape,由它派生出3个派生类:
//  Circle(圆形)、Rectangle(矩形)、Triangle(三角形),
//  用一个函数printArea分别输出以上三者的面积,3个图形的数据在定义对象时给定。

#include <iostream>
using namespace std;
//定义抽象基类Shape
class Shape
{
public:
	virtual double area() const = 0;//纯虚函数
};

//定义Circle类
class Circle :public Shape
{
public:
	Circle(double r) :radius(r) { }//构造函数
	virtual double area() const { return 3.14159 * radius * radius; };//定义虚函数
protected:
	double radius;//半径
};

class Rectangle :public Shape//定义Rectangle类
{
public:
	Rectangle(double w, double h) :width(w), height(h) { }//构造函数
	virtual double area() const { return width * height; }//定义虚函数
protected:
	double width, height;                              		//宽与高
};
class Triangle :public Shape
{
public:
	Triangle(double w, double h) :width(w), height(h) { }//构造函数
	virtual double area() const { return 0.5 * width * height; }//定义虚函数
protected:
	double width, height;//宽与高
};
//输出面积的函数
void printArea(const Shape &s)
{
	cout << s.area() << endl;
}                            	//输出s的面积
int main()
{
	Circle circle(12.6);          //建立Circle类对象circle
	cout << "area of circle    =";
	printArea(circle);            //输出circle的面积
	Rectangle rectangle(4.5, 8.4);//建立Rectangle类对象rectangle
	cout << "area of rectangle =";
	printArea(rectangle);         //输出rectangle的面积
	Triangle triangle(4.5, 8.4);  //建立Triangle类对象triangle
	cout << "area of triangle  =";
	printArea(triangle);          //输出triangle的面积
	return 0;
}

//area of circle = 458.759
//area of rectangle = 37.8
//area of triangle = 18.9

5.编写一个程序,定义抽象基类Shape,由它派生出5个派生类: Circle(圆形)、Square(正方形)、Rectangle(矩形)、Trapezoid(梯形)、 Triangle(三角形)。用虚函数分别计算几种图形面积,并求它们之和。 要求用基类指针数组,使它每一个元素指向一个派生类对象。

【解】

//12.5
//5.编写一个程序,定义抽象基类Shape,由它派生出5个派生类:
//  Circle(圆形)、Square(正方形)、Rectangle(矩形)、Trapezoid(梯形)、
//  Triangle(三角形)。用虚函数分别计算几种图形面积,并求它们之和。
//  要求用基类指针数组,使它每一个元素指向一个派生类对象。

#include <iostream>
using namespace std;
//定义抽象基类Shape
class Shape
{
public:
	virtual double area() const = 0;//纯虚函数
};

//定义Circle(圆形)类
class Circle :public Shape
{
public:
	Circle(double r) :radius(r) { }//构造函数
	virtual double area() const { return 3.14159 * radius * radius; };//定义虚函数
protected:
	double radius;//半径
};
//定义Square(正方形)类
class Square :public Shape
{
public:
	Square(double s) :side(s) { }//构造函数     
	virtual double area() const { return side * side; }//定义虚函数
protected:
	double side;
};
//定义Rectangle(矩形)类
class Rectangle :public Shape
{
public:
	Rectangle(double w, double h) :width(w), height(h) { }//构造函数
	virtual double area() const { return width * height; }//定义虚函数
protected:
	double width, height;//宽与高
};
//定义Trapezoid(梯形)类
class Trapezoid :public Shape
{
public:
	Trapezoid(double t, double b, double h) :top(t), bottom(t), height(h) { }//构造函数
	virtual double area() const { return 0.5 * (top + bottom) * height; }//定义虚函数
protected:
	double top, bottom, height;//上底、下底与高
};
//定义Triangle(三角形)类
class Triangle :public Shape
{
public:
	Triangle(double w, double h) :width(w), height(h) { }//构造函数
	virtual double area() const { return 0.5 * width * height; }//定义虚函数
protected:
	double width, height;//宽与高
};
int main()
{
	Circle circle(12.6);               //建立Circle类对象circle
	Square square(3.5);                //建立Square类对象square
	Rectangle rectangle(4.5, 8.4);     //建立Rectangle类对象rectangle
	Trapezoid trapezoid(2.0, 4.5, 3.2);//建立Trapezoid类对象trapezoid
	Triangle triangle(4.5, 8.4);       //建立Triangle类对象
	Shape * pt[5] = { &circle,&square,&rectangle,&trapezoid,&triangle };
	//定义基类指针数组pt, 使它每一个元素指向一个派生类对象
	double areas = 0.0;//areas为总面积
	for (int i = 0; i < 5; i++)
	{
		areas = areas + pt[i]->area();
	}                     	//累加面积
	cout << "total of all areas=" << areas << endl;//输出总面积
	return 0;
}

//total of all areas = 574.109

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值