【C++之纯虚函数与抽象类1】圆形、矩形、三角形的面积

题目要求

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

——谭浩强的《C++面向对象程序设计》第6章习题第4小题

虚函数

虚函数,就是在基类声明函数是虚拟的,在派生类中才正式定义的函数。虚函数的作用就是在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数

在运用虚函数后,基类指针指向派生类对象,就能调用派生类的虚函数。用同一指针变量,可以调用同一类族中不同类的虚函数,也就是对同一消息,不同对象有不同的响应方式。

虚函数声明格式:

virtual <返回类型> <函数名> (<参数表>)
{<函数体>}

如果某类中的一个成员函数被说明为虚函数,则意味着该成员函数在派生类中可能存在着不同的实现。

  1. 基类中用 virtual 声明成员函数为虚函数。在派生类中重新定义同名函数,让它具有新的功能。

  2. 在派生类中重新定义此函数时,要求函数名、函数类型、参数个数和类型与基类的虚函数完全相同,并根据需要重新定义函数体。C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数自动成为虚函数,因此,对派生类的虚函数中的virtual说明可以省略。

  3. 定义一个指向基类对象的指针变量,并让它获得同一类族中某个对象的地址。

  4. 用该指针变量调用虚函数,调用的就是该对象所属类的虚函数。

  5. 只有非静态的成员函数才可以说明为虚函数。

  6. 构造函数不能说明为虚函数,但是析构函数可以说明为虚函数。

虚函数与函数重载的区别

  1. 函数重载处理的是同一层次上的同名函数问题,虚函数处理的是不同派生层次中的同名函数问题。

  2. 函数重载要求函数名相同,但函数的参数或类型不同;虚函数处理要求的是不仅函数名相同,而且函数参数和类型也要相同。

  3. 虚函数是实现动态多态性的必要条件,而静态多态性是通过函数重载实现的。

动态关联

函数重载和用对象名调用成员函数,在编译时即可确定其调用的函数属于哪个类,其过程称为静态关联

运行期间把虚函数和类对象绑定在一起,此过程称为动态关联,这种多态性是动态的多态性。

动态关联实现的三个条件:

  1. 基类与派生类定义中要有同名的虚函数;
  2. 通过基类对象的指针或者引用访问虚函数;
  3. 基类对象的指针或引用有明确的使用对象。

纯虚函数

只声明,不定义的虚函数称为纯虚函数。纯虚函数的作用是为派生类提供一个一致的接口(界面)。它的定义留给派生类来做,派生类根据需要来定义各自的实现。

纯虚函数声明格式:

virtual 函数类型 函数名(参数表) = 0;

一个类可以说明一个或多个纯虚函数。

纯虚函数与函数体为空的虚函数的区别

纯虚函数:

  • 根本没有函数体
  • 所在的抽象类,不能直接进行实例化

空的虚函数:

  • 函数体为空
  • 所在的类可以实例化

共同的特点:

  • 可以派生出新的类

抽象类

带有纯虚函数的类就是抽象类。抽象类的主要作用是为整个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。

  1. 抽象类是一个特殊的类,是为了抽象和设计的目的而建立的,它处于继承层次结构的最上层,即只能用作其它类的基类不能定义对象

  2. 从一个抽象类派生的类必须提供纯虚函数的实现代码或在该派生类中仍将它说明为纯虚函数,否则编译错。

  3. 抽象类不能用作参数类型、函数返回类型或显式转换的类型,但可以说明指向抽象类的指针和引用,此指针可以指向它的派生类,实现多态性。

  4. 构造函数不能是虚函数,析构函数可以是虚函数。

程序

/*
*************************************************************************
@file:    main.cpp
@date:   2020.12.9
@author: Xiaoxiao
@brief:   圆形、矩形、三角形的面积
@blog:    https://blog.csdn.net/weixin_43470383/article/details/110880376
*************************************************************************
*/

#include<iostream>
using namespace std;

class Shape // 抽象基类
{
public:
	virtual void printArea() = 0; // 纯虚函数
};

class Circle :public Shape // 定义 Circle 类
{
public:
	Circle(float r) :radius(r) {}; // 定义构造函数
	virtual void printArea() // 对虚函数再定义
	{
		cout << "Area of Circle:" << endl << 3.14159 * radius * radius << endl;
	}

private:
	float radius;
};

class Rectangle :public Shape // 定义 Rectangle 类
{
public:
	Rectangle(float w, float h) :width(w), height(h) {}; // 定义构造函数
	virtual void printArea() // 对虚函数再定义
	{
		cout << "Area of Rectangle:" << endl << width * height <<  endl;
	}

private:
	float width;
	float height;
};

class Triangle :public Shape // 定义 Triangle 类
{
public:
	Triangle(float w, float h) :width(w), height(h) {}; // 定义构造函数
	virtual void printArea() // 对虚函数再定义
	{
		cout << "Area of Triangle:" << endl << 0.5 * width * height << endl;
	}

private:
	float width;
	float height;
};

int main()
{
	Circle circle(4.5);        // 建立 Circle 类对象 circle
	circle.printArea();        // 输出 circle的面积

	Rectangle rectangle(2, 6); // 建立 Rectangle 类对象 rectangle
	rectangle.printArea();     // 输出 rectangle 的面积

	Triangle triangle(3, 5);   // 建立 Triangle 类对象 
	triangle.printArea();      // 输出 triangle 的面积

	system("pause");
	return 0;
}

运行结果

运行结果
输出:
Area of Circle:
63.6172
Area of Rectangle:
12
Area of Triangle:
7.5

  • 3
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,这是一个关于面向对象编程的问题。以下是代码实现: ```c++ #include <iostream> #include <cmath> using namespace std; class Shape { public: virtual double area() = 0; // 定义纯虚函数 }; class Circle : public Shape { private: double radius; public: Circle(double r) : radius(r) {} virtual double area() { return M_PI * radius * radius; } }; class Rectangle : public Shape { private: double width, height; public: Rectangle(double w, double h) : width(w), height(h) {} virtual double area() { return width * height; } }; class Triangle : public Shape { private: double base, height; public: Triangle(double b, double h) : base(b), height(h) {} virtual double area() { return 0.5 * base * height; } }; void printArea(Shape* shape) { cout << "面积为:" << shape->area() << endl; } int main() { Circle circle(5); Rectangle rectangle(4, 6); Triangle triangle(3, 8); printArea(&circle); printArea(&rectangle); printArea(&triangle); return 0; } ``` 这段代码中,我们定义了一个抽象基类`Shape`,其中包含了一个纯虚函数`area()`。由`Shape`类派生`Circle`、`Rectangle`和`Triangle`三个具体的形状类,并且实现了它们的`area()`方法。我们还定义了一个`printArea()`函数,用于输一个形状的面积。最后,我们进行了一些简单的测试,分别输了三种形状的面积,并且使用`Shape`类的指针输了它们的面积。 注意,在定义抽象基类时,我们使用了`virtual`关键字和`= 0`来定义纯虚函数,这是C++中实现抽象类的方法。一个抽象类不能被实例化,只能被用作其他类的基类。抽象类的子类必须实现父类中定义的纯虚函数,否则它也会被视为抽象类

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不雨_亦潇潇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值