静态多态 动态多态

一. 静态多态

1. 何为静态多态?

又称编译期多态,即在系统编译期间就可以确定程序将要执行哪个函数。例如:函数重载,通过类成员运算符指定的运算。

2. 示例代码

函数重载示例:

class A {
public:
    A() {}
    A( int x ) {}
    void f() {}
    void f( int x ) {}
};

class B {
public:
    B() {}
    void f() {}
    void f( int x ) {}
};

以上,类A中两个A()是函数重载,两个f()是函数重载,类B同理。

二. 动态多态

1. 何为动态多态?

动态多态是利用虚函数实现运行时的多态,即在系统编译的时候并不知道程序将要调用哪一个函数,只有在运行到这里的时候才能确定接下来会跳转到哪一个函数。
动态多态是在虚函数的基础上实现的,而实现的条件有:
(1) 在类中声明为虚函数
(2) 函数的函数名,返回值,函数参数个数,参数类型,全都与基类的所声明的虚函数相同(否则是函数重载的条件)
(3) 将子类对象的指针(或以引用形式)赋值给父类对象的指针(或引用),再用该指向父类对象的指针(或引用)调用虚函数
如此,便可以实现动态多态,程序会按照实际对象类型来选择要实行的函数具体时哪一个。

2. 示例代码

(1) 非多态
#include <iostream>
using namespace std;

class A {
public:
    A() {}
    void f() { cout << "A::f() is called.\n"; }
};

class B : public A {
public:
    B() {}
    void f() { cout << "B::f() is called.\n"; }
};

int main() {
    A a;
    B b;

    A *p1 = &a;
    A *p2 = &b;

    p1->f();
    p2->f();

    return 0;
}
运行结果
A::f() is called.
A::f() is called.

在这种情况下,我们会发现程序的输出结果并不是我们想要的,而是两次调用的f()函数都是基类的。这是因为使用的是基类指针,而且基类中没有将f()声明为虚函数,所以每次调用都会使用基类的方法。

(2)多态
#include <iostream>
using namespace std;

class A {
public:
    A() {}
    virtual void f() { cout << "A::f() is called.\n"; }
};

class B : public A {
public:
    B() {}
    virtual void f() { cout << "B::f() is called.\n"; }
};

int main() {
    A a;
    B b;

    A *p1 = &a;
    A *p2 = &b;

    p1->f();
    p2->f();

    return 0;
}
运行结果
A::f() is called.
B::f() is called.

这样,也就实现了动态多态,程序可以按照我们期望的方式正确输出。

三. 总结

建议在基类中,如果含有虚函数,就将类的析构函数声明为虚析构函数,以避免在调用时发生错误。

### 静态多态动态多态的概念 静态多态动态多态是 C++ 中实现多态性的两种主要方式。它们分别对应于编译时多态运行时多态性。 #### 编译时多态静态多态静态多态是指在编译期间就已经确定的具体行为,通常由重载函数、运算符重载以及模板机制来体现。这种类型的多态不会引入额外的性能开销,因为所有的决策都在编译期完成[^1]。 ```cpp #include <iostream> // 函数重载 (Function Overloading) void display(int value) { std::cout << "Integer: " << value << std::endl; } void display(double value) { std::cout << "Double: " << value << std::endl; } int main() { display(42); // 调用整数版本 display(3.14); // 调用双精度浮点数版本 return 0; } ``` 上述代码展示了函数重载的应用场景,其中 `display` 函数针对不同参数类型提供了不同的实现逻辑。这是典型的静态多态实例[^3]。 #### 运行时多态动态多态动态多态则是在程序执行过程中才决定调用哪个方法的行为,这依赖于虚函数机制。基类定义了一个虚函数后,派生类可以对其进行覆盖,当通过指向子类对象的指针或引用来调用该虚函数时,会自动绑定到对应的派生类实现上[^1]。 ```cpp #include <iostream> using namespace std; class Animal { public: virtual void speak() const { cout << "Animal speaks." << endl; } }; class Dog : public Animal { public: void speak() const override { cout << "Dog barks!" << endl; } }; class Cat : public Animal { public: void speak() const override { cout << "Cat meows!" << endl; } }; int main(){ Animal *a = new Dog(); a->speak(); // 输出 "Dog barks!" delete a; a = new Cat(); a->speak(); // 输出 "Cat meows!" return 0; } ``` 在这个例子中,尽管变量 `a` 的声明类型为 `Animal*`,但由于其实际上存储的是指向 `Dog` 或者 `Cat` 对象的地址,因此最终调用了相应子类中的 `speak()` 方法。这就是动态多态的实际应用案例[^2]。 ### 总结对比 | 特征 | 静态多态 | 动态多态 | |--------------------|-----------------------------------|-----------------------------| | **发生时间** | 编译时期 | 运行时期 | | **实现手段** | 函数/运算符重载 模板 | 继承加虚函数 | | **效率影响** | 不会产生任何运行时成本 | 可能会有较小的性能损失 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值