【C++】—多态(上)动态多态

一、多态
1、 概念:同一事物表现出的多种形态,同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
2、 举例子:

#include<windows.h>
class WashRoom
{
public:
    void GoToManWashRoom()
    {
        cout << "Man ---> Please Left" << endl;
    }
    void GoToWomanWashRoom()
    {
        cout << "Woman ------> Please Right" << endl;
    }
};

class Person
{
public:
    virtual void GoToWashRoom(WashRoom& wc) = 0;
};

class Man :public Person
{
public:
    virtual void GoToWashRoom(WashRoom& wc)
    {
        wc.GoToManWashRoom();
    }
};

class Woman :public Person
{
public:
    virtual void GoToWashRoom(WashRoom& wc)
    {
        wc.GoToWomanWashRoom();
    }
};

void TestWashRoom()
{
    WashRoom wc;
    Person* p = NULL;
    for (int i = 0; i <10; ++i)
    {
        if ((rand()) & 0x01)
            p = new Man;
        else
            p = new Woman;
        p->GoToWashRoom(wc);
        delete p;
        Sleep(1000);
    }
}

int main()
{
    TestWashRoom();
    return 0;
}

3、 多态的分类
(1)静态多态:编译器在编译期间来确定程序的行为(确定具体调用哪个函数)

A:函数重载

B:泛型编程

(2)动态多态:程序运行时来确定程序的行为(确定具体调用哪个函数)
4、 动态多态实现条件
(1) 基类中必须包含虚函数,在派生类中必须对基类的虚函数进行重写
(2) 必须通过基类指针或引用调用虚函数

<think>我们被要求回答关于C++多态的分类,特别是静态多态动态多态的区别和实现方式。根据引用[1][2][3][4]的内容,我们可以总结如下:1.多态分为静态多态动态多态。2.静态多态(编译期多态):在编译期间确定具体执行哪个函数。实现方式包括函数重载和模板(泛型编程)。3.动态多态(运行时多态):在程序运行时才能确定具体调用的函数。实现方式主要是通过虚函数和继承。接下来,我们详细说明两者的区别和实现方式。一、静态多态(StaticPolymorphism)静态多态也称为编译期多态,是指在编译阶段就确定了程序执行哪个函数。主要包括两种方式:-函数重载(Overloading):在同一作用域内,函数名相同但参数列表不同(参数类型、个数、顺序不同),编译器根据调用时传递的参数类型来决定调用哪个函数。-模板(Templates):通过模板实现泛型编程,编译器根据模板参数的类型在编译时生成具体的代码。示例:函数重载```cpp#include<iostream> usingnamespace std; voidprint(inti){cout <<"Integer: "<< i<< endl; }void print(double f) {cout<< "Float:" <<f <<endl;} intmain(){print(5);//调用voidprint(inti)print(5.5);//调用voidprint(doublef)return0; }```示例:模板```cpp#include <iostream>using namespacestd;template <typename T> Tadd(T a, Tb){return a+ b; }int main() {cout<< add(1,2)<< endl;//调用add<int>(int,int)cout<< add(1.1,2.2)<< endl;//调用add<double>(double,double)return0; }```二、动态多态(Dynamic Polymorphism)动态多态也称为运行时多态,是指在程序运行时根据对象的实际类型来确定调用的函数。实现动态多态需要满足三个条件:-继承:存在基类和派生类的继承关系。-虚函数:基类中使用虚函数声明,派生类中重写该虚函数。-基类指针或引用:使用基类的指针或引用指向派生类对象,并通过该指针或引用调用虚函数。示例:```cpp#include <iostream>using namespacestd;class Shape{ public:virtual voiddraw(){//虚函数cout <<"Drawinga shape." <<endl;}}; classCircle :public Shape{ public:void draw() override{ //重写虚函数cout<< "Drawing acircle."<< endl;} };classRectangle: publicShape {public:voiddraw()override {cout<< "Drawing arectangle."<< endl;} };int main() {Shape* shape1 =new Circle();Shape*shape2= newRectangle();shape1->draw();//实际调用Circle::draw()shape2->draw();//实际调用Rectangle::draw()deleteshape1;delete shape2;return0; }```三、静态多态动态多态的区别根据引用[4]的内容,我们可以总结如下区别: |特性|静态多态|动态多态||--------------|------------------------------|------------------------------||决定时期|编译期|运行期||实现机制|函数重载、模板|虚函数、继承| |接口形式|隐式接口(基于有效表达式)|显式接口(基于函数签名)| |效率|较高(无运行时开销)|较低(有虚函数表查找开销)| |灵活性|较低(编译时确定)|较高(运行时绑定)| |类型检查|编译时类型检查|运行时类型检查(如dynamic_cast)|四、总结静态多态动态多态都是C++中实现多态性的重要手段,它们适用于不同的场景:-静态多态:在编译期确定,效率高,但缺乏运行时灵活性。适用于性能要求高且类型在编译期可确定的场景。-动态多态:在运行期确定,通过虚函数机制实现,提供了运行时的灵活性,支持面向对象设计中的开闭原则。适用于需要运行时动态绑定的场景,如框架设计、插件系统等。根据引用[2]和[3],动态多态通过虚函数表(vtable)实现,每个含有虚函数的类都有一个虚函数表,表中存放了虚函数的地址。当通过基类指针调用虚函数时,程序会根据实际对象的虚函数表找到正确的函数地址。最后,我们生成相关问题。</think>### C++ 多态分类:静态多态动态多态 #### 1. **静态多态(编译期多态)** - **实现方式**: - **函数重载**:同名函数根据参数列表不同实现不同功能 ```cpp void print(int i) { /*...*/ } // 整型版本 void print(double d) { /*...*/ } // 浮点版本 ``` - **模板编程**:编译器根据类型参数生成具体代码 ```cpp template <typename T> T add(T a, T b) { return a + b; } // 适用于int, double等类型 ``` - **特点**: - 在编译期确定具体调用的函数 - 无运行时开销,效率高 - 接口为隐式约束(基于有效表达式) - **原理**: - 编译器通过名称修饰(name mangling)区分重载函数 - 模板实例化时生成类型特化代码 #### 2. **动态多态(运行时多态)** - **实现方式**: - **虚函数机制**:通过虚函数表(vtable)实现 ```cpp class Base { public: virtual void draw() { /* 基类实现 */ } // 虚函数声明 }; class Derived : public Base { public: void draw() override { /* 派生类实现 */ } // 重写虚函数 }; // 使用基类指针调用 Base* obj = new Derived(); obj->draw(); // 运行时确定调用Derived::draw() ``` - **必要条件**: - 继承关系 - 虚函数声明(`virtual`关键字) - 基类指针/引用指向派生类对象 - **特点**: - 在运行时确定具体调用的函数 - 通过虚函数表实现动态绑定 - 有运行时开销(虚表查找) - 接口为显式函数签名 #### 3. **核心区别** | 特性 | 静态多态 | 动态多态 | |--------------|------------------------------|------------------------------| | **决定时机** | 编译期 | 运行期 | | **实现机制** | 模板具现化/函数重载 | 虚函数/继承 | | **开销** | 无运行时开销 | 虚表查找开销 | | **接口形式** | 隐式(表达式约束) | 显式(函数签名) | | **灵活性** | 编译时类型绑定 | 运行时动态绑定 | | **典型应用** | STL算法、模板元编程 | 框架设计、插件系统 | #### 4. **技术原理对比** - **静态多态**: - 编译器生成多份特化代码 - 类型检查在编译期完成 - 错误在编译时暴露 - **动态多态**: - 虚函数表存储函数指针 ```mermaid graph LR A[对象] --> B[虚表指针] B --> C[虚函数表] C --> D[draw()地址] C --> E[resize()地址] ``` - 运行时通过对象头部的虚表指针查找函数地址 - 支持`dynamic_cast`和`typeid`运行时类型识别 > **关键结论**:静态多态通过编译期代码生成实现零开销抽象,适合性能敏感场景;动态多态通过运行期绑定实现灵活扩展,适合需要运行时不确定性的系统设计[^1][^2][^3][^4]。 --- ### 相关问题 1. 虚函数表(vtable)在C++中是如何具体实现的? 2. 模板元编程中如何实现编译期条件判断(类似if-else)? 3. 动态多态中的虚函数调用比普通函数调用慢多少? 4. 什么情况下应该优先选择静态多态而非动态多态? 5. C++20概念(concepts)如何增强静态多态的类型安全?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值