当前位置: 首页 > news >正文

七、C++速通秘籍—静态多态(编译期)

上一章节:

六、C++速通秘籍—深入探索new delete-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146489554?spm=1001.2014.3001.5502

本章节代码:

cpp/staticPolymorphic.cpp · CuiQingCheng/cppstudy - 码云 - 开源中国https://gitee.com/cuiqingcheng/cppstudy/blob/master/cpp/staticPolymorphic.cpp

目录

上一章节:

本章节代码:

一、引言

二、静态多态:编译期的 “角色定制”

1、定义编译期确定行为的多态

2、实现方式:函数重载/运算符重载/模板编程

2.1、函数重载:同一作用域内,函数名相同但参数不同(类型、数量、顺序)。

2.2、运算符重载:让运算符适配自定义。

2.3、模板编程:

(1)、函数模板:代码的魔法复制机

使用场景

(2)、类模板:数据结构的百变魔方

使用场景

四、总结

下一章节:


一、引言

        C++ 多态就如同一个演员能在不同的戏剧里扮演多种角色。在编程里,多态意味着一个接口能有多种实现方式。

按照多态实现的方式,可分为如下:

二、静态多态:编译期的 “角色定制”

1、定义编译期确定行为的多态

静态多态是编译器在编译阶段就确定调用哪个函数的多态形式,就像电影开拍前,演员的角色早已写进剧本。

2、实现方式:函数重载/运算符重载/模板编程

2.1、函数重载:同一作用域内,函数名相同但参数不同(类型、数量、顺序)

例如计算不同类型数据的加法:

    // 函数重载
    int add(int a, int b) 
    {
         return a + b;
    }

    double add(double a, double b) 
    { 
        return a + b; 
    }

调用时,编译器根据参数类型自动匹配对应函数,就像快递员按地址精准送货。

2.2、运算符重载:让运算符适配自定义。

例如下重载"+" 跟"<<"

/***
 *  C++ 多态
 *      一、静态多态(编译期确定)
 *          1、函数重载
 *          2、运算符重载
 *          3、模板编程: 模板函数,模板类
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>


// arithmetic unit
// 运算单元
class AritchmeticUnit{
    double m_dPartOne{0.0};
    double m_dPartTwo{0.0};
public:
    AritchmeticUnit(){}
    AritchmeticUnit(double real1, double real2):m_dPartOne(real1), m_dPartTwo(real2){}
    
    // 函数重载
    int add(int a, int b) 
    {
         return a + b;
    }

    double add(double a, double b) 
    { 
        m_dPartOne = a;
        m_dPartTwo = b;
        return a + b; 
    }
    
    // 运算符重载
    AritchmeticUnit operator+(const AritchmeticUnit& a1){
        AritchmeticUnit retA(m_dPartOne + a1.m_dPartOne, m_dPartTwo + a1.m_dPartTwo);
        return retA;
   }

   // 重载 << 运算符用于输出
   friend std::ostream& operator<<(std::ostream& out, const AritchmeticUnit& c) {
        out <<"value: " << c.m_dPartOne << ", " << c.m_dPartTwo;
        return out;
    }   

};

int main()
{
    AritchmeticUnit aritUnit;
    int iRet = aritUnit.add(3, 5);
    double dRet = aritUnit.add(4.12, 3.85);
    printf("iRet = %d, dRet=%f\n", iRet, dRet);

    AritchmeticUnit aritUnit1(3.88, 6.66);

    AritchmeticUnit aritUnit2 = aritUnit1+aritUnit;

    std::cout <<"aritUnit2: " << aritUnit2 <<std::endl;
    return 0;
}

注意:C++中不能重载的运算符 .( 成员运算符 ),.*(成员指针运算符),::( 作用域运算符 ),?:(条件运算符), sizeof

2.3、模板编程:

(1)、函数模板:代码的魔法复制机

想象一下,你是一位忙碌的魔法师,需要为不同类型的物品施展 “减法魔法”。如果每次都要为不同类型的物品编写一个特定的减法咒语,那可真是太繁琐了。好在 C++ 为我们提供了函数模板这个神奇的魔法复制机,让我们可以轻松应对各种类型的减法

通俗一句话解释,不同对象的,相同处理行为的抽象。

    // 函数模板
    template<typename T, typename M>
    T subtr(T& a, M& b)
    {
        T ret;
        // 打印数的实际类型
        const char* chT = typeid(T).name();
        const char* chM = typeid(M).name();
        std::cout << "T type: " << chT << std::endl;
        std::cout << "M type: " << chM << std::endl;
        if(!(std::strcmp("i",chT) && std::strcmp("d",chM)))
        {
            return ret;
        }

        T mB = (T)b;
        if (mB > a)
        {
            ret = mB - a;
        }
        else{
            ret = a - mB;
        }
        return ret;
    }
使用场景

函数模板的使用场景非常广泛,尤其适用于那些需要对不同类型数据执行相同操作的情况。比如,我们可以编写一个通用的排序函数模板,用于对不同类型的数组进行排序;或者编写一个通用的查找函数模板,用于在不同类型的容器中查找元素。函数模板让我们可以编写一次代码,就能够处理多种类型的数据,大大提高了代码的复用性和可维护性

(2)、类模板:数据结构的百变魔方

实例展示

现在,让我们把目光转向类模板,它就像是一个百变魔方,可以根据我们的需求变成各种不同的数据结构。假设我们想要创建一个通用的栈类,用于存储不同类型的数据。使用类模板,我们可以轻松实现这个目标。

// 定义一个类模板
template <typename T>
class Stack {
public:
    // 入栈操作
    void push(T element) {
        m_elements.push_back(element);
    }

    // 出栈操作
    T pop() {
        if (m_elements.empty()) {
            throw std::out_of_range("Stack is empty");
        }
        T top = m_elements.back();
        m_elements.pop_back();
        return top;
    }

    // 判断栈是否为空
    bool isEmpty() const {
        return m_elements.empty();
    }
private:
    std::vector<T> m_elements;
};

// 创建一个存储整数的栈
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    std::cout << "Popped from intStack: " << intStack.pop() << std::endl;
    std::cout << "Popped from intStack: " << intStack.pop() << std::endl;

    // 创建一个存储字符串的栈
    Stack<std::string> stringStack;
    stringStack.push("Hello");
    stringStack.push("World");
    std::cout << "Popped from stringStack: " << stringStack.pop() << std::endl;
    std::cout << "Popped from stringStack: " << stringStack.pop() << std::endl;
使用场景

类模板适用于那些需要创建通用数据结构或算法的情况。比如,标准模板库(STL)中的 vector、list、map 等容器类,都是使用类模板实现的。类模板让我们可以编写通用的数据结构和算法,而不需要为每种数据类型都编写一个特定的实现。这不仅提高了代码的复用性,还使得代码更加简洁和易于维护。

四、总结

静态多态像编译期的 “定制剧本”,靠函数重载、运算符重载和模板编程实现高效适配;让程序在统一接口下绽放多样可能,这正是 C++ 强大表现力的精彩体现!

下一章节:

八、C++速通秘籍—动态多态(运行期)-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/147004745?spm=1001.2014.3001.5502

相关文章:

  • 预测函数控制(PFC)——理论、应用与实践
  • 学透Spring Boot — 014. Spring MVC的自动配置
  • CANoe CAPL——CAN CAPL函数
  • jQuery 文本属性值
  • OceanBase生态2.0:如何实现“三分天下有其一”?
  • 应用层自定义协议与序列化
  • 【AI提示词】大学教授学术阅读(读论文)
  • 基于SpringBoot的售楼管理系统【附源码】
  • 记一次常规的网络安全渗透测试
  • SpringMVC与SpringCloud的区别
  • 区块链赋能知识产权保护:用技术捍卫创作者的权利
  • 下载安装Node.js及其他环境
  • 什么是异步?
  • ChatGPT-4o 在汉字显示上进步巨大
  • 解锁多邻国:全方位语言学习新体验
  • Gateway 网关 快速开始
  • NAT技术、代理服务器和内网穿透
  • Dubbo(36)如何进行Dubbo的性能调优?
  • CMake使用教程
  • 【中间件】使用ElasticSearch提供的RestClientAPI操作ES
  • 学校培训网站开发/百度霸屏推广多少钱一个月
  • wordpress做购物网站/seo业务培训
  • 网站建设需要什么研究条件/企业如何做网站
  • 简单网站css样式/怎么在平台上做推广
  • windows10网站建设/谷歌搜索引擎优化seo
  • 怎么做购物网站的分类目录/成都新一轮疫情