• STL学习笔记(第二章 C++及其标准程序库简介)


    本章重点是介绍与C++标准程序库相关的几个最重要的语言新特性

    template(模板)

    程序库中几乎所有东西都被设计成template形式。所谓templates,是针对“一个或多个尚未明确的型别”所撰写的函数或类别。

    下面是一个典型例子

     template<class T>
     inline const T& max(const T& a,const T& b)
     {
          return a < b ? b : a;
     {

    template并非一次编译便产生出社和所有型别的代码,而是针对被使用的某个(或某组)型别进行编译。因此你必须先提供它的某个实作品才能调用。

    Nontype Templates参数(非型别模板参数)

    型别(type)可作为template参数,非型别(nontype)也可以作为template参数。例如可以把标准类别bitset<>的bits数量以template参数指定。下面定义两个由bits构成的容器,分别为32个bits空间和50个bits空间。

    bitset<32> flags32;
    bitset<50> flags50;

    Default Template Parameters(缺省模板参数)

    Template classes可以有缺省参数。例如以下声明,允许你使用一个或两个template参数来声明MyClass对象。

    template <class T,class container = vector<T> >
    class MyClass;

    关键字typename

    关键字typename被用来作为型别之前的标识符号。考虑下面例子:

    template <class T>
    class MyClass
    {
           typename T::SubType *ptr;
           ...
    };

    这里,typename指出SubType是class T中定义的一个型别,因此ptr是一个指向T::SubType型别的指针。

    如果没有关键字typename,SubType会被当成一个static成员,于是T::SubType *ptr会被解释为型别T内的数值SubType与ptr的乘积。

    typename还可以在template声明中用来替代关键字class:

    template <typename T>
    class MyClass;

    Member Template(成员模板)

    class member function可以是个template,但这样的member template既不能是virtual,也不能有缺省参数,例如:

    class MyClass
    {
          ...
          template <class T>
          void f(T);
    };

    这里的MyClass::f声明了一个成员函数集,使用任何型别参数。这个特性通常用来为template classes中的成员提供自动型别转换。

    如果使用类模板,其型别必须和调用端所提供的对象的型别完全吻合:

    template <class T>
    class MyClass
    {
        private:
            T value;
        public:
            void assign(const MyClass<T>& x) {value=x.value;}
        ...  
    };
    
    void f()
    {
         MyClass<double> d;
         MyClass<int> i;
         d.assign(d)            //OK
         d.assign(i)             //ERROR
    }
    View Code

    而member template function可以放宽“必须精确吻合”这条规则。只要型别可被赋值,就可以被当做其函数参数。

    template <class T>
    class MyClass{
         private:
             T value;
         public:
             template <class X>
             void assign(const MyClass<X>& x) {value=x.getValue();}
             T getValue () const {return value;}
    };
    
    void f()
    {
         MyClass<double> d;
         MyClass<int> i;
         d.assign(d);   //OK
         d.assign(i);    //OK
    }
    View Code

    因为assign()参数x和*this的型别并不相同,所以不能直接存取MyClass<>的private成员和protected成员,因此要提供类似getValue()之类的东西。

    template constructor是member template的一种特殊形式。template constructor并不遮蔽implicit copy constructor。如果型别完全吻合,implicit copy constructor就会被产生出来并被调用。

    template <class T>
    class MyClass{
       public:
           template <class U>
           MyClass(const MyClass<U>& x);
           ...
    };
    
    void f()
    { 
         MyClass<double> xd;
         MyClass<double> xd2(xd)  //calls built-in copy constructor
         MyClass<int> xi(xd)           //calls template constructor
    }
    View Code

    基本型别的显示初始化(Explicit Initialization)

    如果采用不含参数的、明确的constructor调用语法,基本型别会被初始化为零:

    int i1;            //undefined value
    int i2=int();   //initialized with zero

    这个特性可以确保我们在撰写template程序代码时,任何型别都有一个确切的初值:

    template <class T>
    void f()
    {
        T x=T();
        ...
    }

    关键字explicit

    通过关键字explicit的作用,我们可以禁止“单参数构造函数”被用于自动型别转换。

    class Stack{
        explicit Stack(int size);
        ...
    };

    如果没有explicit,这个构造函数有能力将一个int自动转换成Stack。在这种情况下,可以给Stack指派一个整数值而不会引起任何问题:

    Stack s;
    ...
    s=40  //create a new Stack for 40 elements and assigns it to s

    而使用了explicit的构造函数则会使上述赋值操作导致编译错误。

  • 相关阅读:
    Camera2Raw
    ActiveNotifications
    百度检索技巧
    Android开发ScrollView上下左右滑动事件冲突整理一(根据事件)
    四种方案解决ScrollView嵌套ListView问题
    10 条提升 Android 性能的建议
    Android操作外置SD卡和U盘相关文章
    SQLServer通过链接服务器调用Oracle 存储过程
    Easy Image X2 快速分区-恢复镜像-万能驱动 一站式操作!
    纯净PE推荐——优启通 v3.3.2019.0605
  • 原文地址:https://www.cnblogs.com/runnyu/p/4812476.html
Copyright © 2020-2023  润新知