C++ 多态 (含实例)

源码如下,解释在后面。

#include <iostream>
using namespace std;

class B
{
    
    
public:
	virtual void f1()
	{
    
    
		cout << "B:f1()" << endl;
	}
	virtual void f2()
	{
    
    
		cout << "B:f2()" << endl;
	}
	void g()
	{
    
    
		cout << "B:g()" << endl;
		f1();
		f2();
	}
};

class D :public B
{
    
    
public:
	virtual void f1()
	{
    
    
		cout << "D:f1()" << endl;
	}
	virtual void f3()
	{
    
    
		cout << "D:f3()" << endl;
	}
	void g()
	{
    
    
		cout << "D:g()" << endl;
		f1();
		f2();
	}
};
int main()
{
    
    
	D d;
	D* pd = &d;
	B* pb = &d;
	B b = d;
	b.f1();
	b.f2();
	b.g();
	pb->f1();
	pb->f2();
	pb->g();
	pd->f1();
	pd->f2();
	pd->f3();
	pd->g();
}

在这里插入图片描述
对象直接调用自己的成员方法。
在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述
因为f1()方法增加了virtual关键字,d为D类的实例化对象,动态链接的方式查表,即使父类指针pb指向子类对象,依然调用子类D的实例化对象d的成员方法。
子类D中没有重写(覆盖)f2()方法,所以使用子类对象的成员方法。

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
g()方法前没有virtual,所以是静态链接,直接用指针类型B类内的方法,调用f1()时又因为f1()方法有virtural关键字,所以是动态链接,经过后期绑定后找到该指针指向对象的成员方法,打印出,D:f1(),
调用f2()方法时,基类没有f2(),所以使用继承自基类中的方法,java也同理。

在这里插入图片描述 在这里插入图片描述
删除掉程序内所有virtual关键字后运行结果如下
在这里插入图片描述 在这里插入图片描述

可以发现两者的结果没有不同,virtual的存在就是为了动态多态,动态链接存在的,但此时指针类型指向了它对应的对象类型,所以二者没有什么差异,方法优先使用自己的成员方法,若类内没有重写的方法,便使用继承的基类的方法。
观察结果,因为只没有f2()方法,所有调用基类的该方法,其他方法自动调用自己的。

要求
在这里插入图片描述

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const  double  PI = 3.1415926;

//图形的抽象基类    
class  Shape {
    
    
public:
	virtual  double  Area() = 0;  //求面积,  纯虚函数;    
};

//求二维图形的抽象基类;    
class  Shape2D :public  Shape {
    
    
public:
	virtual  double  Perimeter() = 0;  //求周长,  纯虚函数;    
};

//求三维图形的抽象基类;    
class  Shape3D :public  Shape {
    
    
public:
	virtual  double  Volume() = 0;  //求体积,  纯虚函数;    
};
//派生类,  矩形;    
class  Rectangle : public  Shape2D
{
    
    
public:
	Rectangle(double length, double width) :length_(length), width_(width) {
    
    
	}
	double Area() {
    
    
		return length_ * width_;
	}
	double Perimeter() {
    
    
		return 2 * length_ + 2 * width_;
	}
private:
	double length_;
	double width_;
};
//派生类,  椭圆;    
class  Ellipse :public  Shape2D
{
    
    
public:
	Ellipse(double semimajor, double semiminor) :semimajor_(semimajor), semiminor_(semiminor) {
    
    

	}
	double Area() {
    
    
		return 2 * PI * semiminor_ + 4 * (semimajor_ - semiminor_);
	}
	double Perimeter() {
    
    
		return PI * semimajor_ * semiminor_;
	}
private:
	double semimajor_;
	double semiminor_;
};

//派生类,  圆;    
class  Circle : public  Shape2D
{
    
    
public:
	Circle(double radius) :radius_(radius) {
    
    

	}
	double Area() {
    
    
		return PI * radius_ * radius_;
	}
	double Perimeter() {
    
    
		return PI * 2 * radius_;
	}
private:
	double radius_;
};
//派生类,  球体;    
class  Sphere :public  Shape3D
{
    
    
public:
	Sphere(double radius) :radius_(radius) {
    
    

	}
	double Area() {
    
    
		return 4 * PI * radius_ * radius_;
	}
	double Volume() {
    
    
		return 4.0 / 3.0 * PI * radius_ * radius_ * radius_;
	}
private:
	double radius_;
};
//派生类,  圆柱体;    
class  Cylinder :public  Shape3D
{
    
    
public:
	Cylinder(double height, double radius) :height_(height), radius_(radius) {
    
    

	}
	double Area() {
    
    
		return 2 * PI * radius_ * (height_ + radius_);
	}
	double Volume() {
    
    
		return PI * radius_ * radius_ * height_;
	}
private:
	double height_;
	double radius_;
};
//派生类,  圆锥体;    
class  Cone : public  Shape3D
{
    
    
public:
	Cone(double height, double radius) :height_(height), radius_(radius) {
    
    

	}
	double Area() {
    
    
		return PI * radius_ * (radius_ + sqrt((height_ * height_) + (radius_ + radius_)), 2);
	}
	double Volume() {
    
    
		return 1.0 / 3 * PI * radius_ * radius_ * height_;
	}
private:
	double height_;
	double radius_;
};
class  SumofShape
{
    
    
public:
	//静态函数  计算图形数组面积之和    
	static  double  SumofArea(Shape* shape[], int  n)
	{
    
    
		double sum = 0;
		for (int i = 0; i < n; i++) {
    
    
			sum += shape[i]->Area();
		}
		return sum;
	}
	//静态函数  计算图形数组周长之和  
	static  double  SumofPerimeter(Shape* shape[], int  n)
	{
    
    
		double sum1 = 0;
		for (int j = 0; j < n; j++) {
    
    
			Shape2D* shape2d;
			if (shape2d = dynamic_cast<Shape2D*>(shape[j])) {
    
    
				sum1 += shape2d->Perimeter();
			}
		}
		return sum1;
	}
	//静态函数  计算图形数组的体积之和
	static  double  SumofVolume(Shape* shape[], int  n)
	{
    
    
		double sum2 = 0;
		for (int k = 0; k < n; k++) {
    
    
			Shape3D* shape3d;
			if (shape3d = dynamic_cast<Shape3D*>(shape[k]))
				sum2 += shape3d->Volume();
		}
		return sum2;
	}
private:
	SumofShape() {
    
    
	}  //定义私有构造函数,禁止实例化    
};
int  main() {
    
    

	Rectangle  rectangle(2, 3);
	Ellipse  ellipse(8, 4);
	Circle  circle(3);
	Sphere  sphere(3);
	Cylinder  cylinder(3, 5);
	Cone  cone(3, 4);
	Shape* shape_array[] = {
    
     &rectangle,  &ellipse,  &circle,  &sphere,  &cylinder,  &cone };
	double  sum_of_area = SumofShape::SumofArea(shape_array, 6);
	double  sum_of_perimeter = SumofShape::SumofPerimeter(shape_array, 6);
	double  sum_of_volume = SumofShape::SumofVolume(shape_array, 6);
	cout << "面积总和:" << sum_of_area << "\n周长总和:" << sum_of_perimeter << "\n体积总和:" << sum_of_volume << endl;
	return  0;
}

Guess you like

Origin blog.csdn.net/m0_45311187/article/details/121134766