在面向对象编程时,有一些抽象的概念,而且可以从生活中映射过来,比方如何求一个图形的面积?这里的问题就是:没说明是求什么图形的面积,所以就求不出图形的面积,但是图形在我们生活中却是一个实实在在存在的概念,没有具体的对象实例。
同样在面向对象编程中,这个抽象的概念就对应到抽象类
- 抽象类可用于表示现实世界中的抽象概念
- 抽象类是一种只能定义类型,不能产生对象的类
- 抽象类只能被继承并且重写相关的函数
- 抽象类的直接特征是相关函数没有完整的实现
有了以上概念,我们就能理解图形这个抽象的概念,图形没有具体个例的,仅仅是一个概念,要求图形面积,只能得到具体什么图形,矩形还是圆形,这在面向对象中就像父子之间的继承关系一样,可理解为矩形、圆形都继承自图形,并且矩形、圆形才能产生具体对象
- 在C++中没有抽象类的概念
- C++ 中通过纯虚函数实现抽象类
- 纯虚函数是只定义原型,没有具体实现的函数
- 一个C++类中存在纯虚函数,那么这个类就成为了抽象类
- C++中的抽象类不能定义对象,只能被子类继承,并且在子类中重写纯虚函数,假如子类中没有重写纯虚函数,那么子类也会成为抽象类
C++中纯虚函数的语法规则如下
class className
{
public:
virtual void fun() = 0; //只有声明没有实现
};
在C++类中,要声明纯虚函数,只需要在虚函数后边加"= 0 "即可,不需要实现函数体。下边我们来实现一个图形抽象类,并实现两个子类,一个矩形一个圆形
#include <iostream>
using namespace std;
class Shape //定义一个图形抽象类
{
private:
int m_value;
public:
virtual double area() = 0; //求面积函数为纯虚函数
};
class Rect : public Shape //定义矩形类,继承自图形类
{
private:
double m_height;
double m_width;
public:
Rect(double w, double h)
{
m_height = h;
m_width = w;
}
double area()
{
return m_width * m_height;
}
};
class Circle : public Shape //定义圆形类,继承自图形类
{
private:
double m_Radius;
public:
Circle(double r)
{
m_Radius = r;
}
double area()
{
return 3.14*m_Radius*m_Radius;
}
};
double getArea(Shape* p) //公有函数,参数为图形类指针
{
return p->area(); //计算面积
}
void main()
{
//Shape s; //Error,不能定义抽象类的对象
Circle c(2);
Rect r(4,4);
cout << "Circle area = " << getArea(&c) << endl;
cout << "Rect area = " << getArea(&r) << endl;
system("pause");
}
上边的代码中我们想在main函数中定义一个Shape抽象类对象,但是编译器是不允许的,因为抽象类只能被继承,上边的代码编译执行如下
使用抽象类,是的我们的代码比较统一,只要传入相应的子类对象地址就可以,这也是多态。
在面向对象中,还有一种类成为接口,接口是一种特殊的抽象类,体现在C++中需要满足如下
- 类中没有定义任何成员变量
- 所有的成员函数都是公有的纯虚函数
- 接口是一种特殊的抽象类
接口拥有抽象类的所有属性,即只能被继承,不能实例化,下边就是一个接口的示例,我们定义的是一个求图形周长跟面积的接口
#include <iostream>
using namespace std;
class Shape //定义一个图形接口类
{
public:
virtual double area() = 0; //求面积函数为纯虚函数
virtual double perimeter() = 0; //求周长函数为纯虚函数
};
class Rect : public Shape //定义矩形类,继承自图形类接口
{
private:
double m_height;
double m_width;
public:
Rect(double w, double h)
{
m_height = h;
m_width = w;
}
double area() //重写纯虚函数
{
return m_width * m_height;
}
double perimeter() //重写纯虚函数
{
return 2*(m_width + m_height);
}
};
class Circle : public Shape //定义圆形类,继承自图形类接口
{
private:
double m_Radius;
public:
Circle(double r)
{
m_Radius = r;
}
double area() //重写纯虚函数
{
return 3.14*m_Radius*m_Radius;
}
double perimeter() //重写纯虚函数
{
return 2*3.14*m_Radius;
}
};
double getArea(Shape* p) //公有函数,参数为图形类指针
{
return p->area(); //计算面积
}
double getPerimeter(Shape* p)
{
return p->perimeter();
}
void main()
{
Circle c(2);
Rect r(4,4);
cout << "Circle area = " << getArea(&c) << endl;
cout << "Circle perimeter = " << getPerimeter(&c) << endl;
cout << "Rect area = " << getArea(&r) << endl;
cout << "Rect perimeter = " << getPerimeter(&r) << endl;
system("pause");
}
以上就是我们定义的图形接口,并在子类中重写纯虚函数,下边是编译输出
接口的概念,是的我们的面向对象的封装性更加完善
总结
- 抽象类用于描述现实世界中的抽象概念
- 抽象类只能被继承不能创建对象
- C++中通过纯虚函数来实现抽象类
- 类中只有公有纯虚函数时成为接口
- 接口是一种特殊的抽象类