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