模板与泛型编程(代码片段)

tianzeng tianzeng     2023-04-18     653

关键词:

  C++ templates的最初发展动机很直接:让我们得以建立“类型安全”的容器如vector,list和map。然而当愈多人用上templates,他们发现templates有能力完成愈多可能的变化。容器当然很好,但泛型编程——写出的代码和其所处理的对象类型彼此独立——更好。STL算法如for_each, find 和 merge 就是这一类编程的成果。最终人们发现,C++ template机制自身是一部完整的图灵机:它可以被用来计算任何可计算的值。于是导出了模板元编程,创造出“在C++编译器内执行并于编译完成时停止执行”的程序。容器反倒只成为C++ template 上的一小部分。然而,尽管template 的应用如此宽广,有一组核心观念一直支撑着所有基于template的编程。那些观念便是本章焦点。

条款41 : 了解隐式接口和编译期多态

  面向对象编程世界总是以显式接口和运行期动态解决问题。如下代码所示:

class Widget

    public:
        Widget();
        virtual ~Widget();
        virtual std::size_t size() const;
        virtual void normalize();
        void swap(Widget& other);     // 条款25
        .....
;

void doProcessing(Widget& w)

    if (w.size() > 10 && w != someNastyWidget)
    
        Widget temp(w);
        temp.normalize();
        temp.swap(w);
    

  1.由于w的类型被声明为Widget,所以w必须支持Widget接口。我们可以在源码中找出这个接口,看看它是什么样子,所以我们称为一个显式接口,也就是它在源码中明确可见。

  2.由于Widget的某些成员函数是virtual,w对那些函数的调用将表现出运行期多态,也就是说将于运行期根据w的动态类型(条款37)决定究竟调用哪一个函数。

  Templates及泛型编程的世界,与面向对象有根本不同。在此世界中显式接口和运行期多态仍然存在,但重要性降低。反倒是隐式接口和编译器多态更显重要了。如下:

template<typename T>
void doProcessing(T& w)

    if (w.size() > 10 && w != someNastyWidget)
    
        Widget temp(w);
        temp.normalize();
        temp.swap(w);
    

  3.w 必须支持哪一种接口,系由template中执行于w身上的操作来决定。本例看来w的类型T好像必须支持size,normalize和swap成员函数,copying函数(用来建立temp),不等比较(用来比较someNasty-Widget)等等。这一组表达式(对此template而言必须有效编译)便是T必须支持的一组隐式接口。

  4.凡涉及w的任何函数调用,例如operator>和operator!=,有可能造成template具现化,使这些调用得以成功。这样的具现行为发生在编译期。“以不同的template参数具现化function templates(函数模板)”会导致调用不同的函数,这个便是所谓的编译期多态。(“哪一个函数应该被调用”——发生在编译期; “哪一个virtual函数该被绑定”——发生在运行期)。

  通常,显式接口由函数签名式(也就是函数名称、参数类型、返回类型)构成。

  隐式接口就完全不同了。它并不基于函数签名式,而是由有效表达式组成。

  template参数身上的隐式接口,就像class对象身上的显示接口一个样真实,二者都在编译期完成检查。无法在template中使用“不支持template所要求之隐式接口”的对象,代码编译通不过。

请记住:

  1. classes 和 templates 都支持接口和多态。

  2. 对classes而言接口是显式的,以函数签名为中心。多态则是通过virtual函数发生于运行期。

  3. 对template参数而言,接口是隐式的,奠基于有效表达式。多态则是通过template具现化和函数重载解析发生于编译期。 

 

effectivec++笔记—模板与泛型编程(代码片段)

模板内容很丰富,分两次记录吧条款41:了解隐式接口和编译期多态对应了显示接口和运行期多态。下面一个例子说明:voidfunc(Widget&w)cout<<w.size()<<endl;func参数类型被声明为Widget,所以w必须支持Widget接... 查看详情

模板与泛型编程(代码片段)

...图灵机:它可以被用来计算任何可计算的值。于是导出了模板元编程,创造出“在C++编译器内执行并于编译完成时停止执行”的程序。容器反倒只成为C++template上的一小部分。然而,尽管template的应用如此宽广,有一组核心... 查看详情

c++标准容器库与泛型编程(代码片段)

...红黑树的区别分配器(allocator)STL设计模式OOP和GP模板特化malloc分配内存的一点东西容器listIterator遵循原则vectordeque红黑树容器set和multiset容器map和multimaphashtable(哈希表)迭代器的分类算法算法accumulate算法for_each算法replace、 查看详情

模板与泛型编程——定义模板(代码片段)

一、定义模板1、函数模板  模板定义以关键字template开始,后跟一个模板参数列表,这是一个逗号分隔的一个或多个模板参数的列表,用<>括起来。在模板定义中,模板参数列表不能为空。模板参数表示在类或函数定义中... 查看详情

模板与泛型编程

模板分为函数模板和类模板。函数模板:一个函数模板就像一个公式,可以用来生成针对特定类型的函数版本。模板定义以关键字template开始,后跟一个模板参数列表。模板参数列表时一个以逗号分割的一个后多个模板参数的列... 查看详情

模板与泛型编程——模板实参推断(代码片段)

一、模板实参推断  对于函数模板,编译器利用调用中的函数实参来确定其模板参数。从函数实参来确定模板实参的过程被称为模板实参推断。在模板实参推断过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这... 查看详情

[c++潜心修炼]模版与泛型编程(代码片段)

文章目录泛型编程模版的基本介绍作用一:函数模版作用二:类模版总结泛型编程​可谓人如其名,泛着一词,就说明了通用,之前写代码的时候是不是逻辑一样但是参数不一样就需要在拷贝一份,修改变... 查看详情

第十六章模板与泛型编程

16.1知识点:当我们调用一个模板函数时,即向一个模板传递实参,编译器用此函数实参来推断模板实参,并将该模板实参(即实参的类型)绑定到模板参数(即T)。实例化:编译器用模板实参代替对应的模板参数来创建出一个... 查看详情

java泛型泛型简介(泛型类|泛型方法|静态方法的泛型|泛型类与泛型方法完整示例)(代码片段)

...数化类型,主要作用在类,方法,接口上;java泛型与C++模板:Java中的泛型,是仿照C++中的模板开发的,目的是让开发者可以写出通用,灵活的代码;伪泛型:Java中的泛型,是伪泛型,Java泛型开发好之后,在编译阶段就将泛型相关的信... 查看详情

boolanstl与泛型编程第一周笔记

...都有,还是那句话,我再抄一遍没意义,所以我把C++Primer模板那一章的习题做了一些,这章的题除了涉及到模板,还整合了很多之前学习容器的时候的习题(往往是用模板实现类或者函数,其中有很多使用容器的练习) 查看详情

c++标准容器库与泛型编程(代码片段)

...红黑树的区别分配器(allocator)STL设计模式OOP和GP模板特化malloc分配内存的一点东西容器listIterator遵循原则vectordeque红黑树容器set和multiset容器map和multimaphashtable(哈希表)迭代器的分类算法算法accumulate算法for_each算法replace、... 查看详情

c++标准容器库与泛型编程(代码片段)

...红黑树的区别分配器(allocator)STL设计模式OOP和GP模板特化malloc分配内存的一点东西容器listIterator遵循原则vectordeque红黑树容器set和multiset容器map和multimaphashtable(哈希表)迭代器的分类算法算法accumulate算法for_each算法replace、... 查看详情

[geekband]stl与泛型编程

本篇文章主要介绍泛型算法中的变易、排序、数值算法。一、变易算法所谓变易算法是指那些改变容器中的对象的操作。1.1copy组template <classInputIterator, classOutputIterator> OutputIteratorcopy(InputIteratorfirst... 查看详情

dart学习笔记-枚举与泛型(代码片段)

一、枚举1、枚举是一种有穷序列集的数据类型2、使用关键字enmu定义一个枚举3、常用于代替常量,控制语句等enumSeasonspring,summer,autumn,wintervoidmain()varcurrentSeason=Season.spring;switch(currentSeason)caseSeason.spring:print("1-3月" 查看详情

c++泛型编程(代码片段)

目录1.什么是泛型编程?2.函数模板(1)函数模板概念(2)函数模板格式(3)函数模板的原理(4)函数模板的实例化1)隐式实例化:让编译器根据实参推演模板参数的实际类型2)显式实例化:在函数名后的<>中指定模板参数... 查看详情

c++泛型编程(代码片段)

目录1.什么是泛型编程?2.函数模板(1)函数模板概念(2)函数模板格式(3)函数模板的原理(4)函数模板的实例化1)隐式实例化:让编译器根据实参推演模板参数的实际类型2)显式实例化:在函数名后的<>中指定模板参数... 查看详情

java?不定类型与泛型的使用解决list继承参数(代码片段)

?表示不确定的数据类型。下面我们来看看怎么使用。定义模型和子模型@DatapublicclassModelStringid;Stringname;Stringdesc;@DatapublicclassSubModelextendsModelStringsubName;定义List泛型接口和实现publicinterfaceMultiModelService/***多模 查看详情

kotlin泛型②(可变参数vararg关键字与泛型结合使用|使用[]运算符获取指定可变参数对象)(代码片段)

文章目录一、可变参数vararg关键字与泛型结合使用二、使用[]运算符获取指定可变参数对象一、可变参数vararg关键字与泛型结合使用如果泛型类型T的参数是vararg可变参数,则在接收可变参数时,需要使用Array<outT>类型的变量进... 查看详情