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

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

题目要求


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


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


虚函数


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


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


虚函数声明格式:


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


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


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


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


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


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


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


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


虚函数与函数重载的区别


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


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


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


动态关联


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


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


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


基类与派生类定义中要有同名的虚函数;

通过基类对象的指针或者引用访问虚函数;

基类对象的指针或引用有明确的使用对象。


纯虚函数


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


纯虚函数声明格式:


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


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


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


纯虚函数:


根本没有函数体

所在的抽象类,不能直接进行实例化

空的虚函数:


函数体为空

所在的类可以实例化

共同的特点:


可以派生出新的类


抽象类


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


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


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


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


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


程序


/*
*************************************************************************
@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


相关文章
|
C++
C++一分钟之-虚函数与抽象类
【6月更文挑战第21天】在C++中,虚函数与抽象类是多态的基础,增进类间耦合与灵活性。虚函数实现动态绑定,抽象类定义不可实例化的接口。关键点包括:记得使用`virtual`,避免滥用虚函数,确保派生类实现纯虚函数。抽象类不能直接实例化,派生类必须实现所有纯虚函数。通过实例代码学习和实践,能更好地掌握这些概念以优化代码设计。
226 2
|
10月前
|
存储 编译器 C++
【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)
本文介绍了面向对象编程中的多态特性,涵盖其概念、实现条件及原理。多态指“一个接口,多种实现”,通过基类指针或引用来调用不同派生类的重写虚函数,实现运行时多态。文中详细解释了虚函数、虚函数表(vtable)、纯虚函数与抽象类的概念,并通过代码示例展示了多态的具体应用。此外,还讨论了动态绑定和静态绑定的区别,帮助读者深入理解多态机制。最后总结了多态在编程中的重要性和应用场景。 文章结构清晰,从基础到深入,适合初学者和有一定基础的开发者学习。如果你觉得内容有帮助,请点赞支持。 ❤❤❤
1264 0
|
Serverless 编译器 C++
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
286 4
|
算法 C++
【算法单调栈】 矩形牛棚(C/C++)
【算法单调栈】 矩形牛棚(C/C++)
|
存储 编译器 C语言
从C语言到C++_23(多态)抽象类+虚函数表VTBL+多态的面试题(下)
从C语言到C++_23(多态)抽象类+虚函数表VTBL+多态的面试题
323 1
|
存储 编译器 Linux
从C语言到C++_23(多态)抽象类+虚函数表VTBL+多态的面试题(中)
从C语言到C++_23(多态)抽象类+虚函数表VTBL+多态的面试题
207 1
|
数据安全/隐私保护 C++
C++中的虚函数、纯虚函数与函数重写的技术性探讨
C++中的虚函数、纯虚函数与函数重写的技术性探讨
304 0
|
编译器 C语言 C++
从C语言到C++_23(多态)抽象类+虚函数表VTBL+多态的面试题(上)
从C语言到C++_23(多态)抽象类+虚函数表VTBL+多态的面试题
248 0
|
11月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
9月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
382 12