IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++抽象基类ABC理念(Abstract Base Class)(纯虚函数) -> 正文阅读

[C++知识库]C++抽象基类ABC理念(Abstract Base Class)(纯虚函数)

??????? 对于继承来说,有时候is-a规则并不是看上去的那么简单,比如正在开发一个图形程序,程序会显示圆和椭圆。椭圆有长轴和短轴两个数据成员,当长轴等于短轴时,就相当于是一个圆了。因此我们可以将椭圆类作为父类,圆类作为特殊的子类,但是这会带来一些问题。实际上圆并不需要两个数据成员来刻画,用一个半径就能够刻画了。

一.抽象基类理念

????? 对于上面这种问题,我们可以从Ellipse(椭圆)和Circle(圆)类中抽象出它们的共性,将这些特性放到一个ABC(抽象基类)中。再从这个ABC类派生出Circle 和Ellispse类。

二.抽象类(向上强制转换)

????? 所谓抽象类,就是从别的类中抽出其共性而得到的,因此抽象类并不能被创建!!这很重要。

但是抽象类指针却可以指向其派生类,从而统一管理。在我们这个例子中就是BaseEllipse指针可以指向Circle和Ellipse。

BaseEllipse* p  = nullptr;
p = new(Circle);
p->showAxis();

???? 向上强制转换:将派生类引用或指针转换为基类引用或指针,使公有继承不需要进行显式类型转换。

???? 向下强制转换:将基类引用或指针转换为派生类引用或指针,这是不合法的。因为is-a关系通常是不可逆的。简单的说,你不能保证基类一定能用派生类的方法。毕竟,如果可以的话,那干嘛还需要派生类?

三.纯虚函数介绍

??????? 纯虚函数的声明类似如下,就是在虚函数的基础上加个 = 0,这样的声明代表着该函数为空,即未定义,自然不用实现。实际上当一个类中存在一个纯虚函数时,这个类就变成了抽象类

virtual double Area() const = 0;

注意:
(1)纯虚函数没有函数体;
(2)最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是虚函数”;
(3)这是一个声明语句,最后有分号。?

四.例子实现以及注意点

?? 以下为应用ABC的一个例子,小记一下要点把。

1.在基类中protectd中的内容,子类可以访问,但是外部访问不到。即如果 用Circle 实例化一个对象a ,a是访问不到setx的。

? 而在基类中的private,是更强的,子类不能访问,因此需要在基类中定义一些方法来让子类调用方法访问,因此在我的理解里protected 是用来方便开后门的。

2.上文所说只要基类拥有一个纯虚函数,该类就是一个抽象类了。对于继承抽象类的子类来说,其还是一个抽象类。??是不是很疑惑,确实是这样,但是是可以变成具体类的,但是要遵循一定的规则。

? 必须必须,对抽象类的纯虚函数进行改写。而且必须格式一样,如下所示。

1.纯虚函数
virtual double Area() const = 0;
2.1 错误重写(少了const)
virtual double Area(){return M_PI*_duanzhou*_duanzhou;};//这里是一个错误的例子,对纯虚函数的重写必须与其格式一致,这里少写了const,因此 Ellipse还是个抽象类。
2.2正确重写
virtual double Area()const{return M_PI*_duanzhou*_duanzhou;};//正确

?3.注意这里子类的构造函数,对于自类而言,它只能赋值给自己的数据成员,对于基类private中的内容它是访问不到的。因此需要使用成员初始化列表传递给基类构造函数。下面提供了两种方式,请注意第一种,蛮有趣的。

//实现一
Circle::Circle(double r, double x, double y): _r(r), BaseEllipse(x,y){};
//实现二
Circle::Circle(double r, double x, double y):BaseEllipse(x,y) {
    _r = r;

4.我写了一个重载加法,如下所示,刚开始脑抽把cir定义成 const Circle &cir了,结构cir怎么都访问不了其基类的public方法getx和gety。

? 因为对于const对象而言,它只能访问const类方法,所以不行。

5.脑抽++,刚开始写继承的时候写的是clss Circle:BaseEllipse,都没有写public,死活访问不到基类的方法。

Circle &Circle::operator+(Circle &cir) {
    this->_r += cir._r;
    //how to add the x and y
    this->setx(cir.getx());//if const Circle &cir then I cannot use the BaseClass's public functions;
    this->sety(cir.gety());
}
//
// Created by chenweiyu on 2022/3/30.
//

#ifndef CHAPTER13_BASEELLIPSE_H
#define CHAPTER13_BASEELLIPSE_H
#include <iostream>
#include <string>
#include <math.h>
using std::cout;
using std::cin;
using std::endl;
using std::string;

class BaseEllipse {
private:
    double _x;//中心x坐标
    double _y;//中心y坐标
protected:
    void setx(double x){
        _x = x;
    }
    void sety(double y){
        _y = y;
    }
public:
    double getx()const{return _x;};
    double gety()const{return _y;} ;
    virtual double Area() const = 0;
    virtual ~BaseEllipse(){};
    BaseEllipse(double x = 0,double y = 0){ _x = x; _y= y;};
    void Move(double x,double y){ _x = x; _y = y;};
    void showAxis() const{
        cout<<"now the x is "<<_x<<" now the y is "<<_y<<endl;
    }
};

class Circle:public BaseEllipse{
private:
    double _r;
public:
    Circle(double r = 0,double x = 0,double y = 0);
    virtual double Area() const {return M_PI* pow(_r,2);} ;//this must be virtual
    Circle & operator+(Circle &cir);
    virtual ~Circle(){};
};

class Ellipse:BaseEllipse{//1.这里少了继承的区域 因此创建的对象并不能访问showAxis等抽象类的函数。
private:
    double _changzhou;
    double _duanzhou;
public:
    Ellipse(double chang,double duan,double x,double y): BaseEllipse(x,y){_changzhou=chang;_duanzhou=duan;};
    virtual double Area(){return M_PI*_duanzhou*_duanzhou;};//2.这里是一个错误的例子,对纯虚函数的重写必须与其格式一致,这里少写了const,因此 Ellipse还是个抽象类。
};


#endif //CHAPTER13_BASEELLIPSE_H

下面是BaseEllipse.cpp中的代码,我基本都写了内联,所以这里的比较少。

//
// Created by chenweiyu on 2022/3/30.
//

#include "BaseEllipse.h"

Circle::Circle(double r, double x, double y): _r(r), BaseEllipse(x,y){};



Circle &Circle::operator+(Circle &cir) {
    this->_r += cir._r;
    //how to add the x and y
    this->setx(cir.getx());//if const Circle &cir then I cannot use the BaseClass's public functions;
    this->sety(cir.gety());
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:45:54  更:2022-03-31 23:46:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:04:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码