C++抽象类

1.抽象类概念

C++是一门面向对象的编程语言,而所有的对象都是通过类来描述的,如果一个类没有足够的信息来描述一个具体的对象,这样的类就是抽象类。换句话说,类是具有相同或相似结构、操作和约束规格的对象组成的结合。而对象是某一类的具体实例化。每一个类都是具有某些共同特征的对象的抽象。
例如,我们可以将所有的图形归为图形类,图形类即为一个抽象类(父类),但是对于具体的图形是三角形、四边形或者其他图形,无法准确描述。但是三角形、四边形等又都是继承于图形类的子类。具体是哪一类四边形又可分为正方形、平行四边形等。
实际开发中,并不需要将父类初始化为对象,需要的是子类对象,图形类(父类)不能抽象出任何一种图形,但子类却可以。
简单说,父类只是给出了一个模糊的概念,定义了方法的名称,以纯虚函数方式展示,却并没有给出方法的实现过程,而具体的实现过程,在继承于父类的子类中又大不相同。

1.1、抽象类如何使用

在使用抽象类之前,需要了解为什么要用它。如果是自己独自开发代码,得明白什么情况下、什么地方需要加抽象类;如果是在其他人开发的基础上进行二次开发,那也得知道别人为什么需要在此处加抽象类,不加行不行。
例如在工业控制中,有A、B两种运动控制轴卡可以选择,两种轴卡可以实现相同的功能,如果机台装的是A轴卡,那就启动A轴卡,如果装的是B轴卡,那就启用B轴卡。但是我的程序只有一套,即需要兼容效果,如果后面还需要采购C、D轴卡呢?这个时候就可以引用抽象类的概念,抽象类中定义基础运动控制方式名称,但是不实现,实现方式在不同轴卡中。在启用前,只需要判断是哪种轴卡,后续的代码实现运动控制过程调用的方法名称一样。避免了代码中大量修改。

1.2、抽象类规定

(1)抽象类只能用作其他类的基类,不能建立抽象类对象。
(2)抽象类不能用作参数类型、函数返回类型或显式转换的类型。
(3)可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性。这一条很有用,用抽象类方法名称去兼容子类。

2.抽象类代码示例

搞清除抽象类概念后,以下通过一个简单例子加深对抽象类的理解,例子代码来源:C++的抽象类详解

2.1、抽象类

定义抽象类IShape,抽象类IShape作为基类:只有头文件,没有实现文件

#ifndef SHAPE_H
#define SHAPE_H

#include <string>

using  std::string;

//interface

class IShape
{

public:
	virtual float getArea() = 0; //纯虚函数,获得面积
	virtual string getName() = 0; //纯虚函数,返回图形的名称
};

#endif

2.2、子类1

基于此抽象类的一个子类Circle
头文件:

#ifndef CIRCLE_H
#define CIRCLE_H

#include"IShape.h"

class CCircle : public IShape //公有继承自IShape类

{

public:
	CCircle(float radius); //构造函数

public:

	virtual float getArea(); //实现声明实现两个基类的函数,声明的时候需要加virtual关键字,实现的时候就不需要加virtual关键字了。
	virtual string getName();

private:
	float m_fRadius; //派生类可以拥有自己的成员

};

#endif

cpp实现文件

#include"Circle.h"

CCircle::CCircle(float radius)
	:m_fRadius(radius) //使用构造函数的初始化列表初始化
{

}

string CCircle::getName()
{
	return "CCircle";
}

float CCircle::getArea()  //实现两个基类的函数

{
	return 3.14* m_fRadius* m_fRadius;
}

2.3、子类2

基于抽象类的另一个子类:CRect
头文件

#ifndef RECT_H
#define RECT_H

#include"IShape.h"

class CRect : public IShape
{

public:
	CRect(float nWidth, float nHeight);

public:
	virtual float getArea();
	virtual string getName();

private:
	float m_fWidth; //矩形类具有自己的两个属性,宽和高
	float m_fHeight;
};

#endif

cpp实现文件

#include"Rect.h"

CRect::CRect(float fWidth, float fHeight)
	:m_fWidth(fWidth), m_fHeight(fHeight)
{

}

float CRect::getArea()
{
	return m_fWidth * m_fHeight;
}

string CRect::getName()
{
	return "CRect";
}

2.4、程序入口


#include"Rect.h"
#include"Circle.h"

using namespace std;

int main()
{
	IShape* pShape = NULL; //定义了一个抽象类的指针,注意抽象类不能定义对象但是可以定义指针
	pShape = new CCircle(20.2); //基类指针指向派生类的对象
	cout << pShape->getName() << " " << pShape->getArea() << endl;
	delete pShape; //释放了CCirle对象所占的内存,但是指针是没有消失的,它现在就是一个野指针,我们在使用之前必须对它赋值
	pShape = new CRect(20, 10); //基类指针指向派生类的对象
	cout << pShape->getName() << " " << pShape->getArea() << endl;
	return 0;
}

上述例子中,定义了一个图形基类IShape,只有头文件,基类中定义两种方法,计算面积和返回图形名称,但并没有给出实现方式,也不知道是什么图形,无法实现。圆形类CCircle和矩形类CRect继承于基类IShape,分别实现了面积的计算与返回图形名称两种方法。
在程序入口,以指针pShape 的方式,指代基类IShape,而基类指针再指向子类。

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值