C++零基础教程(抽象类和接口)
@TOC
前言
本篇文章来讲解抽象类和接口的概念,抽象类和接口都需要依靠我们之前讲解的虚函数来实现,那么我们就来看看如何使用虚函数来实现抽象类和接口吧。
一、抽象类概念
抽象类是一种不能直接实例化(即创建对象)的类,它被用作其他类的基类或接口。抽象类通过声明纯虚函数(没有具体实现的虚函数)来定义接口,而派生类必须实现这些纯虚函数才能被实例化。
以下是抽象类的特点和用途:
1.抽象类不能直接实例化:抽象类只能作为基类用于继承,并为派生类提供接口和共享的行为。由于抽象类中存在纯虚函数,没有为其提供具体实现,因此不能直接创建抽象类的对象。
2.包含纯虚函数:抽象类中至少包含一个纯虚函数,通过在函数声明的末尾加上= 0来表示纯虚函数。纯虚函数没有具体的实现,派生类必须提供实现才能实例化。当一个类中有纯虚函数时,该类就成为抽象类。
3.定义接口:抽象类定义了一组纯虚函数,用于声明派生类必须实现的操作。这些纯虚函数可以视为接口,规定了派生类的行为。
4.提供默认实现:抽象类中可以包含非纯虚函数,它们可以有默认实现。这些非纯虚函数提供了通用行为或共享功能,派生类可以选择性地重写这些函数。
5.强迫派生类实现纯虚函数:派生类必须实现基类中的纯虚函数,否则派生类也会被视为抽象类,无法实例化。
6.支持多态性:通过继承抽象类并实现纯虚函数,派生类可以对基类的接口进行自定义实现,并以多态的方式使用这些派生类对象。
抽象类提供了一种定义接口和约束派生类的机制,它是面向对象编程中的重要概念。通过使用抽象类,我们可以设计出具有共享接口的相似对象,并实现代码重用和扩展性。同时,抽象类也允许我们使用多态性来处理不同类型的对象,提高代码的灵活性和可维护性。
二、抽象类例子
当深入OOP(面向对象编程)时,抽象类的一个常见用例是定义一个通用的形状类,并通过派生类实现具体的形状(如矩形、圆形等)。下面是一个用C++实现的示例:
#include <iostream>
// 抽象类 Shape
class Shape {
public:
virtual double getArea() const = 0; // 纯虚函数
virtual double getPerimeter() const = 0; // 纯虚函数
virtual void print() const = 0; // 纯虚函数
};
// 派生类 Rectangle
class Rectangle : public Shape {
private:
double length;
double width;
public:
Rectangle(double l, double w) : length(l), width(w) {}
double getArea() const override {
return length * width;
}
double getPerimeter() const override {
return 2 * (length + width);
}
void print() const override {
std::cout << "Rectangle: length = " << length << ", width = " << width << std::endl;
}
};
// 派生类 Circle
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double getArea() const override {
return 3.14 * radius * radius;
}
double getPerimeter() const override {
return 2 * 3.14 * radius;
}
void print() const override {
std::cout << "Circle: radius = " << radius << std::endl;
}
};
int main() {
Rectangle rectangle(5, 3);
Circle circle(2.5);
Shape* shape1 = &rectangle; // 使用基类指针指向派生类对象
Shape* shape2 = &circle;
shape1->print(); // 多态调用
std::cout << "Area: " << shape1->getArea() << ", Perimeter: " << shape1->getPerimeter() << std::endl;
shape2->print();
std::cout << "Area: " << shape2->getArea() << ", Perimeter: " << shape2->getPerimeter() << std::endl;
return 0;
}
在上述代码中,定义了一个抽象类Shape,并声明了纯虚函数getArea()、getPerimeter()和print(),用于获取形状的面积、周长和打印形状信息。然后通过派生类Rectangle和Circle分别实现这些纯虚函数。
在main()函数中,创建了具体的Rectangle和Circle对象,并使用基类指针Shape* 指向派生类对象。通过多态性,我们可以调用基类指针的函数来实现对派生类对象的操作。最后,使用多态特性打印并计算了各个形状的面积和周长。
三、接口概念
在面向对象编程中,接口是一种定义类行为的抽象规范。它定义了类应该具有的方法和属性,但没有提供具体的实现。接口只关注类提供的操作,而不关心其内部实现细节。
以下是接口的特点和用途:
1.纯虚函数:接口中的方法通常是纯虚函数(C++中的纯虚函数通过= 0表示),即没有具体实现的函数。接口声明了类必须实现的操作,但不指定具体的实现方式。
2.定义行为规范:接口定义了一组方法,并规范了类应该具有的行为。它描述了一个类的功能,提供了对类的使用者的一种合约或承诺。
3.多态性支持:通过实现接口,类可以具备多态性。多态允许使用基类指针或引用来引用派生类的对象,并在运行时调用相应的方法。
4.实现解耦:接口可以将类的实现与其使用者分离,使得类和使用者之间只通过接口定义的方法进行通信。这样可以降低代码的耦合性,使系统更加灵活和可扩展。
5.重用和扩展:接口允许类实现多个接口,从而在不同的上下文中使用相同的类。这样可以实现代码的重用并支持类的扩展。
6.设计契约:接口可以被视为类与使用者之间的契约或协议。通过接口,类向外部世界公开一组操作,使用者通过接口来与类进行交互,而不需要关注其内部实现。
四、接口和抽象类的区别
接口和抽象类是面向对象编程中的两个重要概念,它们在某些方面有相似之处,但也存在一些关键区别。下面是接口和抽象类之间的主要区别:
1.实现方式:接口(Interface)只能定义方法和常量,不能包含具体的实现代码,而抽象类(Abstract Class)可以包含方法的实现代码和属性等成员。
2.继承关系:类通过实现接口来遵循接口定义的行为规范,一个类可以实现多个接口。而抽象类通过继承来扩展或修改其基类的行为。
3.多重继承限制:一个类可以实现多个接口,因此可以具备不同接口的特性。然而,类只能继承一个抽象类,因为大多数编程语言不支持多重继承。
4.构造函数:抽象类可以拥有构造函数,而接口不能具有构造函数。抽象类的构造函数主要用于在实例化时执行一些通用逻辑。
5.默认实现:接口中的方法都是抽象的,没有默认实现。而抽象类可以包含抽象方法和非抽象方法,非抽象方法可以提供默认实现。
6.设计层次:接口用于定义行为规范,将类的实现与使用者解耦。抽象类更倾向于在类的继承层次结构中扮演基类的角色,提供一些通用的行为和属性供子类继承和扩展。
总结
本篇文章就讲解到这里,下篇文章我们继续讲解。
- 点赞
- 收藏
- 关注作者
评论(0)