• 详解C++中的抽象类和接口


    前言

    面向对象编程中的抽象和接口是两个非常重要的概念,它们可以帮助我们实现代码的可重用性、可扩展性和可维护性。在图形界面应用中,我们需要定义一些基本的控件,如按钮、文本框、标签等。这些控件都有一些共同的属性和方法,如位置、大小、背景颜色、字体、点击事件等。我们可以定义一个抽象类 Control,它包含这些共同的属性和方法,然后定义各种具体的控件类,如 Button、TextBox、Label 等,它们继承自 Control 类并实现其接口。这样,我们就可以通过 Control 类型的指针或引用来操作各种控件,实现了多态性,使代码更加简洁,同时也实现的代码的可重性,可扩展性和可维护性。在学习抽象类和接口之前,先了解一下什么是纯虚函数。

    纯虚函数

    纯虚函数是一种特殊的虚函数,它在基类中只有函数声明,没有函数实现。纯虚函数的存在是为了将函数的实现责任交给派生类,而基类只负责定义接口和规范行为。

    纯虚函数的主要作用有以下几点:

    1. 实现接口规范:纯虚函数可以用来定义接口,即基类声明了一些纯虚函数,派生类必须实现这些函数才能创建对象。这样可以确保派生类都具有相同的接口,实现了接口规范。

    2. 强制派生类实现:纯虚函数要求派生类必须实现该函数,否则派生类也会成为抽象类,无法创建对象。这样可以强制派生类实现某些特定的行为,确保派生类的完整性。

    3. 多态性的实现:通过基类的指针或引用调用纯虚函数,可以实现多态性。在运行时,根据指针或引用所指向的对象的实际类型,调用相应的派生类的函数实现,从而实现了多态性。

    纯虚函数的语法形式是在函数声明后面加上 "= 0",例如:

    virtual void function() const = 0;

    需要注意的是,包含纯虚函数的类称为抽象类,抽象类不能创建对象。只有派生类实现了所有的纯虚函数,才能创建对象。

    总之,纯虚函数的存在可以帮助我们定义接口规范、强制派生类实现特定行为,并实现多态性。它是面向对象编程中非常重要的概念之一。

    抽象

    抽象是一种将具体的事物抽象成一些通用的概念或模型的方法。在面向对象编程中,抽象通常是通过定义抽象类或接口来实现的。抽象类是一种不能被实例化的类,它定义了一些抽象方法,这些方法只有方法名和参数列表,没有具体的实现。派生类必须实现这些抽象方法才能被实例化。抽象类通常用于定义一些通用的行为,而具体的实现则由派生类来完成。

    抽象类

    抽象类是一种不能实例化的类,它只能作为其他类的基类来使用。抽象类中包含了至少一个纯虚函数,纯虚函数是没有实现体的虚函数,用“= 0”来标记。抽象类的作用是定义一组抽象接口,让子类来实现。

    1. class Shape {
    2. public:
    3. virtual double area() const = 0; // 纯虚函数
    4. virtual double perimeter() const = 0; // 纯虚函数
    5. };
    6. class Circle : public Shape {
    7. public:
    8. Circle(double r) : radius(r) {}
    9. double area() const override { return 3.14 * radius * radius; }
    10. double perimeter() const override { return 2 * 3.14 * radius; }
    11. private:
    12. double radius;
    13. };
    14. class Rectangle : public Shape {
    15. public:
    16. Rectangle(double w, double h) : width(w), height(h) {}
    17. double area() const override { return width * height; }
    18. double perimeter() const override { return 2 * (width + height); }
    19. private:
    20. double width;
    21. double height;
    22. };

    上面的代码定义了一个抽象类 Shape,它包含了两个纯虚函数 area 和 perimeter。然后定义了两个具体的子类 Circle 和 Rectangle,它们实现了 Shape 的接口。

    下面再以动物园举一个更加通俗易懂的例子,为了帮助你更好理解抽象类。

    假设我们有一个动物园,里面有不同种类的动物,如狗、猫、鸟等。我们希望能够统一管理这些动物,比如让它们都能发出声音。

    我们可以定义一个抽象类 Animal,它有一个纯虚函数 makeSound(),表示动物发出声音的行为。

    1. class Animal {
    2. public:
    3. virtual void makeSound() const = 0; // 纯虚函数
    4. };
    5. class Dog : public Animal {
    6. public:
    7. void makeSound() const override { cout << "汪汪汪!" << endl; }
    8. };
    9. class Cat : public Animal {
    10. public:
    11. void makeSound() const override { cout << "喵喵喵!" << endl; }
    12. };
    13. class Bird : public Animal {
    14. public:
    15. void makeSound() const override { cout << "叽叽喳喳!" << endl; }
    16. };

    在上面的代码中,Animal 是一个抽象类,它定义了一个纯虚函数 makeSound()。然后我们定义了三个具体的动物类 Dog、Cat 和 Bird,它们继承自 Animal 类并实现了 makeSound() 函数。

    现在我们可以创建不同种类的动物对象,并调用它们的 makeSound() 函数来发出声音:

    1. int main() {
    2. Animal* dog = new Dog();
    3. Animal* cat = new Cat();
    4. Animal* bird = new Bird();
    5. dog->makeSound(); // 输出:汪汪汪!
    6. cat->makeSound(); // 输出:喵喵喵!
    7. bird->makeSound(); // 输出:叽叽喳喳!
    8. delete dog;
    9. delete cat;
    10. delete bird;
    11. return 0;
    12. }

    通过抽象类 Animal 和多态性,我们可以统一管理不同种类的动物,并调用它们的共同行为 makeSound(),实现了代码的复用和可扩展性。

    接口

    接口是一种定义了一组方法的抽象类。它只包含函数的声明,没有函数的实现。接口用于定义对象应该具有的行为,而不关心具体的实现细节。通过接口,可以将不同的类归类为同一类型,从而可以使用统一的接口来操作这些对象,而不需要关心具体的对象类型。接口的实现可以通过抽象类来实现。抽象类是一个包含纯虚函数的类,它定义了接口规范,派生类必须实现这些纯虚函数才能创建对象。

    接口是一种特殊的抽象类,它只包含纯虚函数和静态常量,没有数据成员和非虚函数。接口的作用是定义一组纯虚函数,让其他类来实现。

    1. class Printable {
    2. public:
    3. virtual void print() const = 0; // 纯虚函数
    4. };
    5. class Person : public Printable {
    6. public:
    7. Person(string n, int a) : name(n), age(a) {}
    8. void print() const override { cout << name << ", " << age << " years old" << endl; }
    9. private:
    10. string name;
    11. int age;
    12. };
    13. class Book : public Printable {
    14. public:
    15. Book(string t, string a) : title(t), author(a) {}
    16. void print() const override { cout << title << " by " << author << endl; }
    17. private:
    18. string title;
    19. string author;
    20. };

    上面的代码定义了一个接口 Printable,它包含了一个纯虚函数 print。然后定义了两个具体的类 Person 和 Book,它们实现了 Printable 的接口。这样,我们就可以通过 Printable 类型的指针或引用来调用 print 函数,实现了多态性。

    如何使用接口和抽象类来实现多态性

    1. // 定义接口
    2. class Shape {
    3. public:
    4. virtual double getArea() const = 0; // 纯虚函数
    5. virtual double getPerimeter() const = 0; // 纯虚函数
    6. };
    7. // 实现接口的抽象类
    8. class Circle : public Shape {
    9. private:
    10. double radius;
    11. public:
    12. Circle(double radius) : radius(radius) {}
    13. double getArea() const override {
    14. return 3.14 * radius * radius;
    15. }
    16. double getPerimeter() const override {
    17. return 2 * 3.14 * radius;
    18. }
    19. };
    20. class Rectangle : public Shape {
    21. private:
    22. double width;
    23. double height;
    24. public:
    25. Rectangle(double width, double height) : width(width), height(height) {}
    26. double getArea() const override {
    27. return width * height;
    28. }
    29. double getPerimeter() const override {
    30. return 2 * (width + height);
    31. }
    32. };
    33. int main() {
    34. Shape* circle = new Circle(5);
    35. Shape* rectangle = new Rectangle(4, 6);
    36. cout << "Circle Area: " << circle->getArea() << endl; // 输出:Circle Area: 78.5
    37. cout << "Circle Perimeter: " << circle->getPerimeter() << endl; // 输出:Circle Perimeter: 31.4
    38. cout << "Rectangle Area: " << rectangle->getArea() << endl; // 输出:Rectangle Area: 24
    39. cout << "Rectangle Perimeter: " << rectangle->getPerimeter() << endl; // 输出:Rectangle Perimeter: 20
    40. delete circle;
    41. delete rectangle;
    42. return 0;
    43. }

    在上面的代码中,我们定义了一个接口 Shape,它包含了两个纯虚函数 getArea() 和 getPerimeter()。然后我们定义了两个实现了 Shape 接口的抽象类 Circle 和 Rectangle。这两个类分别实现了接口中的两个纯虚函数。

    在主函数中,我们创建了一个 Circle 对象和一个 Rectangle 对象,并通过 Shape 指针来调用它们的 getArea() 和 getPerimeter() 函数。由于 Shape 是一个接口,可以将 Circle 和 Rectangle 对象都归类为 Shape 类型,从而实现了多态性。

    总结

    抽象类和接口都是用于实现多态性的重要概念,它们的区别在于:

    • 抽象类可以包含数据成员和非虚函数,而接口只包含纯虚函数和静态常量。
    • 抽象类可以作为其他类的基类来使用,而接口只能被其他类实现。
    • 抽象类中的纯虚函数可以有实现体,而接口中的纯虚函数没有实现体。

    接口是一种定义了一组方法的抽象类,它只包含函数的声明。接口可以通过抽象类来实现,抽象类是一个包含纯虚函数的类,它定义了接口规范。通过接口和抽象类,可以实现多态性,将不同的类归类为同一类型,并使用统一的接口来操作这些对象。

    总之,抽象和接口是面向对象编程中非常重要的概念,它们可以帮助我们实现代码的可重用性、可扩展性和可维护性。抽象和接口的使用可以让我们更好地设计和组织代码,从而提高代码的质量和效率。

     

  • 相关阅读:
    Typora-Drake主题
    python代码:VOC to cityscapes标注文件转换
    Java基础JDK命令行工具(jpd,jstat,jstack,jinfo)
    Otter改造 增加springboot模块和HTTP调用功能
    Swift--基本运算符与程序流程控制
    Windows及Centos系统升级curl
    Rocksdb LSM Tree Compaction策略
    基于小程序探索如何实现数字传媒内容价值最大化
    无插件播放之http-flv
    Go语言第二篇-基本数据类型与转义字符
  • 原文地址:https://blog.csdn.net/qq_39312146/article/details/133838109