C++虚函数和抽象基类的应用

例子1:main.cpp

#include<iostream>
#include<cstring>
using namespace std;
class Shape {
public:
	virtual float area()const { return 0.0; }//虚函数
	virtual float volume() const { return 0.0; }//虚函数
	virtual void shapeName()const = 0;//纯虚函数

protected:


};
class Point :public Shape {
public:
	Point(float a ,float b ):x(a),y(b){}
	void setPoint(float a, float b) { x = a; y = b; }
	float getX()const { return x; }
	float getY()const { return y; }
	virtual void shapeName()const { cout << "Point:"; }
	friend ostream& operator<<(ostream&,const Point&);
protected:
	float x, y;

};
ostream& operator<<(ostream& out, const Point& p) {
	out << "[" << p.x << "," << p.y << "]";
	return out;
}
class Circle :public Point {
public:
	Circle(float a, float b, float r) :Point(a, b), radius(r) {}
	void setRadius(float r) { radius = r; }
	float getRadius()const { return radius; }
	virtual float area()const { return 3.14159 * radius * radius; }
	virtual void shapeName()const { cout << "Circle:"; }
	friend ostream& operator<<(ostream&, const Circle&);
protected:
	float radius;
};
ostream& operator<<(ostream& out, const Circle& c) {
	out << "[" << c.x << "," << c.y << "],r=" << c.radius << endl;
	return out;
}
class Cylinder :public Circle {
public:
	Cylinder(float a,float b,float r,float h):Circle(a,b,r),height(h){}
	void setHeigth(float h) { height = h; }
	virtual float area()const { return Circle::area() * 2 + 2 * 3.14159 * radius * height; }
	virtual float volume()const { return Circle::area() * height; }
	virtual void shapeName()const { cout << "Cylinder"; }
	friend ostream& operator<<(ostream&, const Cylinder&);
protected:
	float height;

};
ostream& operator<<(ostream& out, const Cylinder& cy) {
	out << "[" << cy.x << "," << cy.y << "],r=" << cy.radius << ",h=" << cy.height << endl;
	return out;
}
int main() {
	Point point(3.2, 4.5);
	Circle circle(2.4, 2.5, 6);
	Cylinder cylinder(3.4, 6.4, 5.2, 10.5);
	point.shapeName();//静态关联
	cout << point << endl;
	circle.shapeName();//静态关联
	cout << circle << endl;
	cylinder.shapeName();//静态关联
	cout << cylinder << endl;
	Shape* pt;//定义基类指针
	pt = &point;//指向Point类对象
	pt->shapeName();//动态关联
	cout << "x=" << point.getX() << "y=" << point.getY() << "\narea=" << pt->area() << "\nvolume=" << pt->volume() << endl;
	pt = &circle;//指针指向Circle对象
	pt->shapeName(); //动态关联
	cout << "x=" << point.getX() << "y=" << point.getY() << "\narea=" << pt->area() << "\nvolume=" << pt->volume() << endl;
	pt = &cylinder;
	cout << "x=" << point.getX() << "y=" << point.getY() << "\narea=" << pt->area() << "\nvolume=" << pt->volume() << endl;
	return 0;
}

输出:

Point:[3.2,4.5]
Circle:[2.4,2.5],

Cylinder[3.4,6.4]

Point:x=3.2y=4.5
area=0
volume=0
Circle:x=3.2y=4.5
area=113.097
volume=0
x=3.2y=4.5
area=512.959
volume=891.96

在主函数中调用有关函数并输出结果,先分别定义了Point类对象point,Circle类对象circle和Cylinder类对象cylinder。然后分别通过对象名point,circle,cylinder调用shapeName函数这属于静态关联,在定义一个指向基类Shape对象的指针变量pt,使它先后指向3个派生类对象point,circle和cylinder然后通过指针调用各个函数,如pt->shapeName(),pt->area(),这时是通过动态关联分别确定应该调用哪个函数。分别输出不同类对象的信息。
**Notice:**纯虚函数是在抽象基类中声明的,只是在抽象基类中它才称为纯虚函数。

例子2: main.cpp

#include<iostream>
#include<cstring>
using namespace std;
class Shape {
public:
	virtual double area()const = 0;//纯虚函数
	virtual ~Shape(){}

};
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 {
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;
}
int main() {
	Circle circle(12.6);
	cout << "area of circle =";
	printArea(circle);
	Rectangle rectangle(4.5, 8.4);
	cout << "area of rectangle =";
	printArea(rectangle);
	Triangle triangle(4.5, 8.4);
	cout << "area of triangle =";
	printArea(triangle);
	return 0;


}

结果:

area of circle =498.759
area of rectangle =37.8
area of triangle =18.9

抽象基类中area也可以不声明为纯虚函数而声明1为虚函数;

virtual double area() const {return 0;}

改动后结果是一样的,可以用派生类对象初始化基类的引用,但此时基类的引用不是派生类对象的别名,而是派生类对象中基类部分的别名。但是在使用虚函数时情况有了变化,利用基类指针指向派生类对象的情况相似,派生类对象中的基类部分原来的虚函数被派生类中定义的虚函数代替,因此可以用基类的引用去访问起所代表的对象的虚函数。此外用s.area()调用area函数是动态关联

例子3: main.cpp

定义一个Shape基类,有它派生5个类,用虚函数分别计算他们的面积并求和。要求使用基类指针数组。

#include<iostream>
#include<cstring>
using namespace std;
class Shape {
public:
	virtual double area()const = 0;//纯虚函数
	virtual ~Shape(){}

};
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 {
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;
};
class Square :public Shape {
public:
	Square(double s):side(s){}
	virtual double area()const { return side * side; }
protected:
	double side;
};
class Trapezoid :public Shape {
public:
	Trapezoid(double t,double b,double h):top(t),bottom(b),height(h){}
	virtual double area()const { return 0.5 * (top + bottom) * height; }

protected:
	double top, bottom, height;
};




int main() {
	Circle circle(12.6);
	Square square(3.5);
	Rectangle rectangle(4.5, 8.4);
	Trapezoid trapezoid(2.0, 4.5, 3.2);
	Triangle triangle(4.5, 8.4);
	Shape* pt[5] = { &circle,&rectangle,&trapezoid,&triangle,&square };
	double areas = 0.0;
	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=578.109

在main函数中分别建立了5个类对象,并定义了一个基类指针数组pt使其每一个元素指向一个派生类对象,啊相当于下面的5个语句

pt[0]=&cicle;
pt[1]=&square;
pt[2]=&rectangle;
pt[3]=&trapezoid;
pt[4]=&triangle;

for 循环的作用是将5个类对象的面积相加。pt[i]->area()是调用指针数组pt中的第i个元素所指向的派生类对象的虚函数area。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值