首页 > 编程语言 >C++零基础教程(抽象类和接口)

C++零基础教程(抽象类和接口)

时间:2023-11-12 10:04:15浏览次数:37  
标签:函数 实现 接口 C++ 基础教程 派生类 抽象类 纯虚

(文章目录)


前言

本篇文章来讲解抽象类和接口的概念,抽象类和接口都需要依靠我们之前讲解的虚函数来实现,那么我们就来看看如何使用虚函数来实现抽象类和接口吧。

一、抽象类概念

抽象类是一种不能直接实例化(即创建对象)的类,它被用作其他类的基类或接口。抽象类通过声明纯虚函数(没有具体实现的虚函数)来定义接口,而派生类必须实现这些纯虚函数才能被实例化。 以下是抽象类的特点和用途:

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.设计层次:接口用于定义行为规范,将类的实现与使用者解耦。抽象类更倾向于在类的继承层次结构中扮演基类的角色,提供一些通用的行为和属性供子类继承和扩展。

总结

本篇文章就讲解到这里,下篇文章我们继续讲解。

标签:函数,实现,接口,C++,基础教程,派生类,抽象类,纯虚
From: https://blog.51cto.com/u_16153875/8325462

相关文章

  • c++ function使用
    一、function介绍funciotn是从c++11开始支持的特性,使用它需要包含<functional>头文件在cppreference中解释为:类模板std::function是一个通用的多态函数包装器。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达......
  • C++ 采用get()和put()读写文件
    在某些特殊的场景中,我们可能需要逐个读取文件中存储的字符,或者逐个将字符存储到文件中。这种情况下,就可以调用get()和put()成员方法实现。C++ostream::put()成员方法通过《C++cout.put()》一节的学习,读者掌握了如何通过执行cout.put()方法向屏幕输出单个字符。我们知道,fstr......
  • C++ 使用getline():从文件中读取一行字符串
    getline()方法从cin输入流缓冲区中读取一行字符串。在此基础上,getline()方法还适用于读取指定文件中的一行数据,本节就给大家做详细的讲解。我们知道,getline()方法定义在istream类中,而fstream和ifstream类继承自istream类,因此fstream和ifstream的类对象可以调用ge......
  • C++ 采用read()和write()读写二进制文件
    以文本形式读写文件和以二进制形式读写文件的区别,并掌握了用重载的>>和<<运算符实现以文本形式读写文件。在此基础上,本节继续讲解如何以二进制形式读写文件。举个例子,现在要做一个学籍管理程序,其中一个重要的工作就是记录学生的学号、姓名、年龄等信息。这意味着,我们需要用一个......
  • C++ 的cout格式化输出
    在某些实际场景中,我们经常需要按照一定的格式输出数据,比如输出浮点数时保留2位小数,再比如以十六进制的形式输出整数,等等。对于学过C语言的读者应该知道,当使用printf()函数输出数据时,可以通过设定一些合理的格式控制符,来达到以指定格式输出数据的目的。例如%.2f表示输出浮点......
  • C++读取单个字符操作
    get()是istream类的成员函数,它有多种重载形式,不过本文只介绍最简单最常用的一种:intget();此函数从输入流中读入一个字符,返回值就是该字符的ASCII码。如果碰到输入的末尾,则返回值为EOF。EOF是EndofFile的缩写。istream类中从输入流(包括文件)中读取数据的成员函数,在把输......
  • 二元子句归结的c++代码分析
      1//Tryfurtherlearntclauseminimizationbymeansofbinaryclauseresolution.2boolSolver::binResMinimize(vec<Lit>&out_learnt)3{4//Preparation:rememberwhichfalsevariableswehavein'out_learnt'.5......
  • L2-037 包装机 (25 分)(C/C++)
    输入样例:344GPLTPATAOMSA3230120220-1输出样例:MATA这道题需要注意的就是当框空的时候,按下0是什么都不会发生的。当对应轨道空的时候,按下对应轨道的数字也是什么都不会发生的当对应轨道不为空,但是框满的时候,需要先把框顶的弹出来,再装进去新的。#include<iostream>#......
  • C++ insert into tables of pgsql via libpq-fe.h and compile by g++-13
    1.Installlibpq-devsudoaptinstalllibpq-devlocatelibpq-fe.h/usr/include/postgresql/libpq-fe.h 2.createtablet1createtablet1(idbigserialnotnullprimarykey,authorvarchar(40)notnull,commentvarchar(40)notnull,contentvarchar(40)notn......
  • C++简单插入排序
    voidinsertSort(inta[],intlen){ inti,j,temp; if(len==1)return; for(i=1;i<len;i++){ if(a[i]<a[i-1]){ temp=a[i]; for(j=i-1;j>=0&&a[j]>temp;j--){ a[j+1]=a[j]; }a[j+1]=temp; ......