C++ 多态性

在本教程中,我们将借助示例了解 C++ 中的多态性。

多态是面向对象编程的一个重要概念。它只是意味着不止一种形式。也就是说,相同的实体(函数或运算符)在不同的场景中表现不同。例如,

C++ 中的 + 运算符用于执行两个特定的功能。当它与数字(整数和浮点数)一起使用时,它执行加法。

int a = 5;
int b = 6;
int sum = a + b;    // sum = 11

当我们将 + 运算符与字符串一起使用时,它会执行字符串连接。例如,

string firstName = "abc ";
string lastName = "xyz";

// name = "abc xyz"
string name = firstName + lastName;

C++ 中的多态性主要体现在以下几个方面:

  1. 函数重载
  2. 运算符重载
  3. 函数覆盖
  4. 虚函数

C++ 函数重载

在 C++ 中,我们可以使用两个具有相同名称的并且具有不同的参数(类型或参数数量)函数。

并且,根据参数的数量/类型,调用不同的函数。例如,

#include <iostream>
using namespace std;

// 两个 int 类型的参数
int sum(int num1, int num2) {
    return num1 + num2;
}

// 两个 double 类型的参数
double sum(double num1, double num2) {
    return num1 + num2;
}

// 三个 int 类型的参数
int sum(int num1, int num2, int num3) {
    return num1 + num2 + num3;
}

int main() {
    cout << "Sum 1 = " << sum(5, 6) << endl;
    cout << "Sum 2 = " << sum(5.5, 6.6) << endl;
    cout << "Sum 3 = " << sum(5, 6, 7) << endl;

    return 0;
}

输出

Sum 1 = 11
Sum 2 = 12.1
Sum 3 = 18

在这里,我们创建了 3 个具有不同参数(参数数量/类型)的 sum() 函数。并且,根据函数调用期间传递的参数,确定调用的是哪一个 sum() 函数。

这是一种编译时多态性,因为编译器在编译程序之前就知道要执行哪个函数。

要了解更多信息,请访问我们的C++ 函数重载教程。

C++ 运算符重载

在 C++ 中,只要我们对用户定义的类型(如对象或结构)进行操作,就可以重载运算符。

我们不能将运算符重载用于基本类型,例如 int, double 等。

运算符重载本质上是函数重载,其中不同的运算符函数具有相同的符号但操作数不同。

并且,根据操作数,执行不同的运算符函数。例如,

C++ 程序重载 ++ 前缀:

#include <iostream>
using namespace std;

class Count {
   private:
    int value;

   public:

    // Constructor to initialize count to 5
    Count() : value(5) {}

    // Overload ++ when used as prefix
    void operator ++() {
        value = value + 1;
    }

    void display() {
        cout << "Count: " << value << endl;
    }
};

int main() {
    Count count1;

    // Call the "void operator ++()" function
    ++count1;

    count1.display();
    return 0;
}

输出

Count: 6

在这里,我们重载了 ++ 操作符,它对 Count 类的对象(本例中的 count1)。

我们使用了这个重载的运算符来直接 count1 对象的成员变量 value

这也是一种编译时多态性

要了解更多信息,请访问我们的C++ 运算符重载教程。

C++ 函数覆盖

C++ 继承中,我们可以在基类及其派生类中拥有相同的功能。

当我们使用派生类的对象调用函数时,会执行派生类的函数而不是基类中的函数。

因此,根据调用函数的对象执行不同的函数。

这在 C++ 中称为函数覆盖。例如,

#include <iostream>
using namespace std;

class Base {
   public:
    virtual void print() {
        cout << "Base Function" << endl;
    }
};

class Derived : public Base {
   public:
    void print() {
        cout << "Derived Function" << endl;
    }
};

int main() {
    Derived derived1;

    // Call print() function of Derived class
    derived1.print();

    return 0;
}

输出

Derived Function

在这里,我们使用了 Derived 类中的一个 print() 函数,它覆盖了类 Base 中的 print() 函数。

当我们使用 Derived 对象 derived1 调用 print() 时,它通过执行 Derived 类的 print() 函数来覆盖 Base 中的函数。

这是一个运行时多态性,因为函数调用不是由编译器解析的,而是在运行时解析的。

要了解更多信息,请访问我们的C++ 函数覆盖教程。


C++ 虚函数

在 C++ 中,如果我们使用基类的指针指向派生类的对象,我们可能无法覆盖函数。

在基类中使用虚函数可确保在这些情况下可以覆盖函数。

因此,虚函数实际上属于函数覆盖。例如,

#include <iostream>
using namespace std;

class Base {
   public:
    virtual void print() {
        cout << "Base Function" << endl;
    }
};

class Derived : public Base {
   public:
    void print() {
        cout << "Derived Function" << endl;
    }
};

int main() {
    Derived derived1;

    // pointer of Base type that points to derived1
    Base* base1 = &derived1;

    // calls member function of Derived class
    base1->print();

    return 0;
}

输出

Derived Function

在这里,我们在 Base 类中使用了一个虚函数 print() 来确保它被 Derived 类中的函数覆盖。

虚函数是运行时多态性

要了解更多信息,请访问我们的C++ 虚拟函数教程。

为什么是多态性?

多态性允许我们创建一致的代码。例如,

假设我们需要计算一个圆和一个正方形的面积。为此,我们可以创建一个 Shape 类并从中派生两个类 CircleSquare

在这种情况下,在两个派生类中创建一个具有相同名称的函数 calculateArea() 而不是创建具有不同名称的函数是有意义的,从而使我们的代码更加一致。