精华内容
下载资源
问答
  • 类模板和模板类
    万次阅读 多人点赞
    2019-07-04 21:10:42

    类模板和模板类

    所谓类模板,实际上是建立一个通用类,其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从而实现了不同类的功能。

    定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,后面是尖括号括起来的模板参数,然后是类名,其格式如下:

    template <typename 类型参数>
    class 类名{
           类成员声明 
    };
    
    或者
    
    template <class 类型参数>
    class 类名{
           类成员声明 
    };
    
    1. template:是一个声明模板的关键字,它表明声明一个模板

    2. 类型参数:通常用C++标识符表示,如T、Type等,实际上是一个虚拟的类型名,现在未指定它是哪一种具体的类型,但使用类模板时,必须将类型参数实例化。

    3. typename和class的作用相同,都是表示其后面的参数是一个虚拟的类名(即类型参数).

    在类声明中,欲采用通用数据类型的数据成员、成员函数的参数或返回类型前面需要加上类型参数。

    如建立一个用来实现求两个数最大值的类模板

    template<typename T>    //模板声明,其中T为类型参数
        class Compare{
          public:
           Compare(T i,T j)
           {
            x = i;
            y = j;
           }
           T max()
           {
            return (x>y)?x:y;
           } 
          private:
           T x,y; 
        };
    

    用类模板定义对象时,采用以下形式:

    类模板名<实际类型名>对象名[(实参表列)];
    

    因此,使用上面求最大值的类型模板的主函数可写成:

     int main()
         {
          Compare<int>com1(3,7);
          Compare<double>com2(12.34,56.78);
          Compare<char>com3('a','x');
          cout<<"其中的最大值是:"<<com1.max()<<endl;
          cout<<"其中的最大值是:"<<com2.max()<<endl;
          cout<<"其中的最大值是:"<<com3.max()<<endl;
          return  0;
         }    
    

    例6.6 类模板compare的使用举例

    #include<iostream.h>
    template<typename T>    //模板声明,其中T为类型参数
    class Compare{
      public:
        Compare(T i,T j)
        {
          x = i;
          y = j;
        }
        T max()
         {
          return (x>y)?x:y;
         } 
     private:
        T x,y; 
    };
    int main()
    {
    Compare<int>com1(3,7);                       //用类模板定义对象com1,此时T被int替代 
    Compare<double>com2(12.34,56.78);            //用类模板定义对象com2,此时T被double替代 
    Compare<char>com3('a','x');                  //用类模板定义对象com3,此时T被char替代 
    cout<<"其中的最大值是:"<<com1.max()<<endl;   
    cout<<"其中的最大值是:"<<com2.max()<<endl;
    cout<<"其中的最大值是:"<<com3.max()<<endl;
    return  0;
    }
    

    程序运行结果是:

    其中的最大值是:7
    其中的最大值是:56.78
    其中的最大值是:x        
    

    在以上例子中,成员函数(其中含有类型参数)是定义类体内的。但是,类模板中的成员函数,也可以在类模板外定义。此时,若成员函数中有参数类型存在,则C++有一些特殊的规定:

    (1)需要在成员函数定义之前进行模板声明;
    (2)在成员函数名前缀上"类名<类型参数>::";
    

    在类模板外定义成员函数的一般形式如下:

    temlate<typename 类型参数>
      函数类型 类名<类型参数>::成员函数名(形参表)
      {
        函数体; 
       }
       
       如上题中成员函数max在类模板外定义时,应该写成:
       template<typename T>
       T Compare<T>::max()
       {
        return (x>y)?x:y;
       } 
    

    //例6.7 在类模板外定义成员函数函数举例。

    #include<iostream.h>
    template<typename T>    //模板声明,其中T为类型参数
    class Compare{
      public:
        Compare(T i,T j)
        {
          x = i;
          y = j;
        }
        T max(); 
     private:
        T x,y; 
    };
    template<class T>
    T Compare<T>::max()
    {
     return (x>y)?x:y;
    }
    int main()
    {
    Compare<int>com1(3,7);                       //用类模板定义对象com1,此时T被int替代 
    Compare<double>com2(12.34,56.78);            //用类模板定义对象com2,此时T被double替代 
    Compare<char>com3('a','x');                  //用类模板定义对象com3,此时T被char替代 
    cout<<"其中的最大值是:"<<com1.max()<<endl;   
    cout<<"其中的最大值是:"<<com2.max()<<endl;
    cout<<"其中的最大值是:"<<com3.max()<<endl;
    return  0;
    } 
    

    /*
    程序运行结果是:

        其中的最大值是:7
        其中的最大值是:56.78
        其中的最大值是:x
    

    此例中,类模板Compare经实例化后生成了3个类型分别为int、double、char的模板类,这3个模板类
    经实例化后又生成了3个对象com1、com2、com3。类模板代表了一类类,模板类表示某一具体的类。关系如下:

                                             类模板
                                            Compare<T>
        实例化成模板类:Compare<int>       Compare<double>     Compare<char>
        实例化模板类对象:com1                 com2                com3
    

    例6.8 类模板Stack的使用举例。

    #include<iostream.h>
    const int size=10;
    template<class T>                     //模板声明,其中T为类型参数 
    class Stack{                          //类模板为Stack 
     public:
      void init()
      {
       tos=0;
      }
      void push(T ob);                    //声明成员函数push的原型,函数参数类型为T类型
      T pop();                            //声明成员函数pop的原型,其返回值类型为T类型
     private:
      T stack[size];                      //数组类型为T,即是自可取任意类型 
      int tos; 
    };
    template<class T>                     //模板声明 
    void Stack<T>::push(T ob)             //在类模板体外定义成员函数push 
    {
      if(tos==size)
       {
        cout<<"Stack is full"<<endl;
        return;
       }
      stack[tos]=ob;
      tos++; 
    }
    template<typename T>                  //模板声明 
    T Stack<T>::pop()                               //在类模板体外定义成员函数push
    {
      if(tos==0)
       {
        cout<<"Stack is empty"<<endl;
        return 0;
       }
      tos--; 
      return stack[tos];  
    }
    int main()
    {
     //定义字符堆栈 
     Stack<char> s1;                        //用类模板定义对象s,此时T被char取代
     s1.init();
     s1.push('a');
     s1.push('b');
     s1.push('c'); 
     for(int i=0;i<3;i++){cout<<"pop s1:"<<s1.pop()<<endl;}
     
     //定义整型堆栈 
     Stack<int> s2;                        //用类模板定义对象s,此时T被int取代
     s2.init();
     s2.push(1);
     s2.push(3);
     s2.push(5); 
     for(int i=0;i<3;i++){cout<<"pop s2:"<<s2.pop()<<endl;} 
     
     return 0; 
    }
    

    /*
    程序运行结果是:

    pop s1:c
    pop s1:b
    pop s1:a
    pop s2:5
    pop s2:3
    pop s2:1 
    

    说明:

    1. 在每一个类模板定义之前,都需要在前面加上模板声明,如

      template

      template
      并且,类模板在使用时,必须在模板类名字后面缀上<类型参数> ,如
      Stack

    2. 如同模板函数一样,模板类也可以有多个类型参数。

    例6.9 有两个类型参数的类模板举例

    #include<iostream.h>
    template<class QQ,class T>                    //声明模板,具有T1,T2两个类型参数 
    class Myclass{                                 //定义模板类Myclass 
      public:
       Myclass(QQ a,T b);
       void show();
      private:
       QQ x;
       T y;
    };
    template<typename QQ,typename T>
    Myclass<QQ,T>::Myclass(QQ a,T b)
    {
     x = a;
     y = b;
    }
    template<class QQ,class T>
    void Myclass<QQ,T>::show()
    {
     cout<<"x="<<x<<","<<"y="<<y<<endl;
    }
    int main()
    {
     Myclass <int,double>m1(12,0.15);               //用类模板定义对象m1,此时T1,T2分别被int、double取代 
     Myclass <int,char*>m2(12,"This a test.");      //用类模板定义对象m2,此时T1,T2分别被int,char*取代
    
     m1.show();
     m2.show();
     
     return 0; 
    }
    /*
    程序运行结果是:
    x=12,y=0.15
    x=12,y=This a test. 
    */
    

    程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
    更多C++相关知识体系,请移步C++知识目录

    更多相关内容
  • C++类模板实例化

    千次阅读 2021-09-04 13:32:18
    C++类模板实例化 文章目录C++类模板实例化1. 简介2. 类模板实例化2.1 隐式实例化(Implicit instantiation)2.2 显示实例化(Explicit instantiation)2.3...类模板本身不是类型、对象或任何其他实体。仅包含模板定义的

    C++类模板实例化

    1. 简介

    该文章主要总结C++类模板实例化的方法。类模板的实例化包含两种:

    1. 隐式实例化(Implicit instantiation)
    2. 显示实例化(Explicit instantiation)

    2. 类模板实例化

    类模板本身不是类型、对象或任何其他实体。仅包含模板定义的源文件不会生成任何代码。为了出现任何代码,必须实例化模板:必须提供模板参数,以便编译器可以生成实际的类(或函数,来自函数模板)。
    类模板必须实例化才能作为一个类来声明和定义类对象,类模板实例化成为模板类,同一个类模板不同的实例之间相互独立。

    2.1 隐式实例化(Implicit instantiation)

    C++代码中发生类模板隐式实例化的条件:

    1. 当代码使用类模板定义对象时,需要在上下文中引用完全定义类型。(例如,当构造此类型的对象时,而不是在构造指向此类型的指针时。 )
    2. 当类型的完整性影响代码时,并且该特定类型尚未显式实例化时,就会发生隐式实例化。

    此外针对类模板成员适用以下准则:

    1. 除非该成员在程序中使用,否则它不会被实例化,也不需要定义。

    下面举例进行说明隐式实例化

    template<class T> 
    struct Z // 模板定义
    {
        void f() {}
        void g(); // 不会被定义
    }; 
    template struct Z<double>; // 显示实例化 Z<double>
    Z<int> a; // 隐式实例化 Z<int>
    Z<char>* p; // 无任何实例化生成
    p->f(); // 隐式实例化 Z<char> and Z<char>::f().
    // Z<char>::g() 不会被声明和定义
    

    错误的实例化
    对类模板进行实例化时,如果只声明了类模板但未定义,则实例化会产生不完整的类类型。如下面代码所示:

    template<class T> 
    class X; // 声明但未定义
     
    X<char> ch;                // error: incomplete type X<char>
    

    2.2 显示实例化(Explicit instantiation)

    显示实例化的方法如下:

    1. template class-key template-name < argument-list >
      显式实例化定义强制实例化它们所引用的类。 它可以出现在模板定义之后的程序中的任何位置,并且对于给定的参数列表,在整个程序中只允许出现一次,不需要诊断。
    2. extern template class-key template-name < argument-list > (since C++11)
      显式实例化声明(外部模板)跳过隐式实例化步骤:否则会导致隐式实例化的代码改为使用其他地方提供的显式实例化定义(如果不存在此类实例化,则会导致链接错误)。这可用于通过在除使用它的源文件之一之外的所有源文件中显式声明模板实例化并在其余文件中显式定义它来减少编译时间。

    类、函数、变量和成员模板特化可以从它们的模板中显式实例化。 成员函数、成员类和类模板的静态数据成员可以从它们的成员定义中显式实例化。
    显式实例化只能出现在模板的封闭命名空间中,除非它使用了qualified-id

    下面举例说明类模板的显示实例化

    namespace N 
    {
      template<class T> 
      class Y // 模板定义
      { 
        void mf() { } 
      }; 
    }
    // template class Y<int>; // 错误: 类模板Y在全局空间不可见
    using N::Y;
    // template class Y<int>; // 错误:在类模板Y定义的区域外实例化
    template class N::Y<char*>;      // 正确: 显示实例化
    template void N::Y<double>::mf(); // 正确: 显示实例化
    

    注意与显示特化冲突:
    如果之前针对同一组模板参数出现了显式特化,则显式实例化无效。

    显示实例化注意事项:

    1. 在显式实例化函数模板、变量模板或类模板的成员函数或静态数据成员或成员函数模板时,仅要求声明可见;
    2. 完整的定义必须出现在类模板、类模板的成员类或成员类模板的显式实例化之前,除非具有相同模板参数的显式特化出现在之前;
    3. 如果使用显式实例化定义类模板的函数模板、变量模板、成员函数模板或成员函数或静态数据成员,则模板定义必须存在于同一编译单元中;
    4. 当显式实例化命名类模板特化时,它充当其每个非继承的非模板成员的相同类型(声明或定义)的显式实例化,这些成员以前未在编译单元中显式特化。 如果此显式实例化是定义,则它也是仅针对此时已定义的成员的显式实例化定义;
    5. 显式实例化定义忽略成员访问说明符:参数类型和返回类型可能是私有的。。

    2.3 类模板中的静态成员

    如果类模板中有静态成员,则每个模板类分别占用一个静态成员。
    以下是类模板中的静态成员正确的初始化方法。

    template <typename T>
    struct S
    {
        static double something_relevant;
    };
    
    template <typename T>
    double S<T>::something_relevant = 1.5;
    
    展开全文
  • 既然对象是以模板生成的,那么又是以什么为模板生成的? 元具有动态改变的能力,给编程带来了更方便的动态性和能力。 新型相比于传统,支持更多特性和机制,有更多的弹性。 文章目录 元 工厂 初始...

    在这里插入图片描述

    元类


    既然对象是以类为模板生成的,那么类又是以什么为模板生成的?

    事实上绝大部分情况下都都不是必须使用元类才能完成开发,但是元类动态地生成类的能力能更方便地解决下面情景的难题:

    • 类在设计时不是所有细节都能确定,有些细节需要程序运行时得到的信息才能决定。
    • 类比实例更重要的情况,如用声明性语言在类声明中直接表示了它的程序逻辑,使用元类来影响类的创建过程就相当有用。

    类工厂


    在Python老版本中,可以使用类工厂函数来创建类,返回在函数体内动态创建的类。
    类工厂的方法是通过一个函数来生产不同的类。类工厂可以是类,就像它们可以是函数一样容易。
    例如:

    def class_with_method(func):
        class klass: pass
        setattr(klass, func.__name__, func)
        return klass
    def say_tip(self):
        print('记得一键三连~')
    Tip = class_with_method(say_tip)
    tip = Tip()
    tip.say_tip()
    

    函数class_with_method是一个类工厂函数,通过setattr()方法来设置类的成员函数,并且返回该类,这个类的成员方法可以通过class_with_methodfunc参数来指定。
    在这里插入图片描述

    初始元类


    在Python2.2之后,type特殊类就是这样的类工厂,即所谓的元类,元类是类的类,类是元类的实例,对象是类的实例。
    元类type使用方法:

    def say_tip(self):
        print('记得一键三连~')
    Tip = type('Tip',(),{'say_tip':say_tip})
    tip = Tip()
    tip.say_tip()
    

    在这里插入图片描述
    元类type首先是一个类,所以比类工厂的方法梗灵活多变,可以自由的创建子类来继承扩展元类的能力。例如:

    class ChattyTypr(type):
        def __new__(cls, name, bases, dct):
            print("分配内存空间给类",name)
            return type.__new__(cls, name, bases, dct)
        def __init__(cls, name, bases, dct):
            print("初始化类", name)
            super(ChattyTypr, cls).__init__(name, bases, dct)
    a = ChattyTypr('Test',(),{})
    

    在这里插入图片描述

    其中,__new__分配创建类和__init__方法配置类是类type内置的基本方法,需要注意的是,第一个蚕食是cls(特指类本身)而非self(类的实例)。

    元类实例化一个类时,类将会获得元类所拥有方法,就像类实例化对象时对象获得类所拥有方法一样,但是注意多次实例化和多次继承的区别:
    在这里插入图片描述

    元类属性


    Python中每一个类都是经过元类实例化而来,只不过这个实例化过程在很多情况下都是由Python解释器自动完成的。那么怎么设置元类的属性?
    每个类都有一个属性__metaclass__用来说明该类的元类,该属性一般由解释器自动设置,不过用户也可以更改该属性来更改类的元类。可以在类的内部直接设置__metaclass__属性,也可以设置全局变量,那么该命名空间下定义所有类的元类都将是全局变量__metaclass__所指定的元类。

    class ChattyTypr(type):
        def __new__(cls, name, bases, dct):
            print("分配内存空间给类",name)
            return type.__new__(cls, name, bases, dct)
        def __init__(cls, name, bases, dct):
            print("初始化类", name)
            super(ChattyTypr, cls).__init__(name, bases, dct)
    class example(metaclass=ChattyTypr):
        def __init__(self):
            print('初始化')
    

    在这里插入图片描述
    在这里插入图片描述

    元类作用


    改变全局变量__metaclass就能改变类的元类,而类又是元类的实例化结果,所以元类可以改变类的定义过程。换句话说,只要改变全局变量__metaclass__就能改变类的定义,这就是元类的作用了。

    class example:
        def __init__(self):
            print('类example初始化')
        def say_tip(self):
            print('记得一键三连')
    a = example()
    a.say_tip()
    class change(type):
        def __new__(cls, name, bases, dict):
            def say_tip(self):
                print('记得点赞关注收藏~')
            dict['say_tip']=say_tip
            return type.__new__(cls, name ,bases, dict)
    class example(metaclass=change):
        def __init__(self):
            print('类example初始化')
        def say_tip(self):
            print('记得一键三连')
    a = example()
    a.say_tip()
    

    在这里插入图片描述

    面向方面和元类


    元类的作用能带来什么实用价值吗?
    实际用途确实有的,接近于面向方面编程(Aspect Oriented Programming,AOP)的核心内容,即所谓的“横切关注点”。

    使用面向对象方法构建软件系统,我们可以利用OO的特性很好地解决纵向问题,因为OO的核心概念(如继承等)都是纵向结构的。
    但是软件系统中往往很多模块/类共享某个行为,或者说某个行为存在于软件的各个部分中,看作是横向 存在于软件之中,它所关注的是软件个部分共有的一些行为,而且很多情况下这种行为不属于业务逻辑的一部分。

    一个软件系统的业务逻辑很大一部分代码都是AOP里所说的横切关注点。例如日志处理、安全检测、事务处理、权限检测等占比很大,几乎每个地方都要调用。AOP的思想就是把这些横切关注点代码都抽取出来,不再在各个软件模块中显示使用。

    以日志处理为例,一般习惯在做一些操作前写上开始模块处理的每个步骤都需要由正常日志和异常日志,那么这个软件光是写日志的代码就要成千上万行了,维护起来相当困难。

    如果部分代码不需要手工写到各个业务逻辑处理的地方,而是把这部分代码独立出来,那么在各个业务逻辑处理的地方,会在运行的时候自动调用这些横切关注点功能,这样代码量就少很多,这就是AOP的核心思想。

    要实现AOP所说的自动调用,有的语言使用AspectJ编译器,Python则使用元类。

    小结


    元类具有动态改变类的能力,给编程带来了更方便的动态性和能力。
    实际使用过程中,需要防止过度使用元类来改变类,过于复杂的元类通常会带来代码难以和可读性差的问题,所以一定要在确实需要使用是再使用元类。

    新型类


    Python在2.2版本后,新引入了两种不同的类:新型类和传统类/经典类。Python的对象世界相比也发生了重大变化。

    新型类VS传统类


    老版本的Python中不是所有的元素都是对象,内置的数值类型都不能被继承,而在版本2.2后,任何内建类型也都是继承自object类的类,凡是继承自类object或者object子类的类都是新型类,而不是继承自object或object子类的都成为传统类

    新的对象模型于传统模型相比有小但是很重要的优势,Python版本对传统类的支持主要是为了兼容性,所以使用类的时候推荐从现在开始直接使用新型类。在Python3版本将放弃兼容性,即Python3.X版本中只存在新型类。

    新型类继承自object或object子类,实际上所有的内建类型都是从object继承而来,可以用issubclass()函数验证,当存在子类和父类关系时返回True,否则返回False。
    在这里插入图片描述

    插播反爬信息 )博主CSDN地址:https://wzlodq.blog.csdn.net/

    静态方法和类方法


    新的对象模型提供了两种类的方法:静态方法和类方法。

    静态方法可以直接被类或类的实例调用,没有常规方法的那样限制(绑定、非绑定、默认第一个参数规则等),即静态函数的第一个参数不需要指定为self,也不需要只有对象(类的实例)才能调用。使用关键字@staticmethod定义。

    如下定义静态方法、常规方法(第一个参为self和不带self两种)

    class Test(object):
        @staticmethod
        def static_tip(str):
            print(str)
        def normal_tip(str):
            print(str)
        def normal_tip2(self,str):
            print(str)
    
    • 使用类调用
      直接使用类调用时,不需要传入self表示具体的类的实例,即报错只传了一个参数。
      在这里插入图片描述
    • 使用对象(类的实例)调用
      使用对象调用时,自动将类实例对象作为第一个参数传给该方法,即报错给了两个参数。
      在这里插入图片描述

    类方法不管是使用类来调用还是使用对象(类的实例)来调用,都是将类作为第一个参数传入。使用关键字@classmethod定义。
    在这里插入图片描述

    特定方法


    1. __new__方法
      当一个类C调用C(*args,**kwds)创建一个C类实例时,Python内部实际上调用的是C.__new__(C,*args,**kwds)。new方法的返回值x就是该类的实例对象,new即用来分配内存生成类的实例。
      注意第一个参数是cls(即这里写的类C),用来接受一个类参数,然后才能返回该类的实例。
      在这里插入图片描述
      使用new方法可以实现一些传统类无法做到的功能,例如让类只能实例化一次:
      在这里插入图片描述
    2. __init__方法
      当调用new方法分配内存创建一个类C对象后,Python判断该实例是该类的实例,然后会调用C.__init__(x,*args,**kwds)来初始化这个实例,x就是new方法的返回值,init即对类实例对象做初始化操作。
      注意第一个参数是self(即这里写的x)表示接受类的实例对象。
      在这里插入图片描述
      上述实例化对象代码c = C()就等价于:
      在这里插入图片描述
    3. __getattribute__方法
      __getattribute__负责实现对象属性引用的全部细节。新型类在调用它自身的类或方法是,实际上都是先通过该方法来调用。
      在这里插入图片描述
      因为新型类调用自身属性和方法时都会先调用__getattribute__方法,所以可以实现一些新功能,如隐藏父类的方法:
      在这里插入图片描述

    特定属性


    内建property类用来绑定类实例的方法,并将其返回值绑定为一个类属性,语法:
    attrib = property(fget=None, fset=None, fdel=None, doc=None)

    设类C通过property创建了属性attrib,x是类C的一个实例。

    • 当引用x.attrib时,会调用fget()方法取值;
    • 当为x.attrib赋值时,会调用fset()方法;
    • 当执行删除del x.attrib时,会调用fdel()方法;
    • doc参数为该属性的文档字符串。

    如果不定义fset()fdel()方法,那么该属性将是一个只读属性。

    property可以方便地将一个函数的返回值转换为属性,这下操作就很灵活方便了。
    比如定义一个长方形类,如果要将它的面积也作为一个属性,就可以用property将计算面积的方法绑定为一个属性:

    class Rectangle(object):
        def __init__(self,width,height):
            self.width=width
            self.height=height
        def getArea(self):
            return self.width*self.height
        area = property(getArea(),doc='长方形的面积')
    

    上述代码中,getArea()是计算面积的方法,使用property将该方法的返回值转换为属性area,这样引用Rectangle的area是,Python会自动使用getArea()计算出面积。同时由于该例中只定义了fget()方法,所以area是一个只读属性。

    super()方法


    新型类提供了一个特殊的方法super()super(aclass,obj)返回对象obj是一个特殊的超对象(superobject)。当我们调用该超对象的一个属性或方法时,就保证了每个父类的实现均被调用且仅仅调用了一次。

    以下时直接调用父类的同名方法,无法避免类A的方法被重复调用:

    class A(object):
        def test(self):
            print('A')
    class B(A):
        def test(self):
            print('B')
            A.test(self)
    class C(A):
        def test(self):
            print('C')
            A.test(self)
    class D(B,C):
        def test(self):
            print('D')
            B.test(self)
            C.test(self)
    d = D()
    d.test()
    

    在这里插入图片描述

    以下时使用super()方法,保证父类方法均调用一次:

    class A(object):
        def test(self):
            print('A')
    class B(A):
        def test(self):
            print('B')
            super(B, self).test()
    class C(A):
        def test(self):
            print('C')
            super(C, self).test()
    class D(B,C):
        def test(self):
            print('D')
            super(D, self).test()
    d = D()
    d.test()
    

    在这里插入图片描述

    小结


    新型类相比于传统类,支持更多特性和机制,有更多的弹性。例如可以定制实例化的过程,尤其时在多重继承的情况下能避免传统类存在的缺陷。而事实上Python3.X版本中已经不存在传统类了,目前传统类存在的意义主要是为了保持之前的兼容性。

    Python系列博客持续更新中

    原创不易,请勿转载本不富裕的访问量雪上加霜
    博主首页:https://wzlodq.blog.csdn.net/
    微信公众号:唔仄lo咚锵
    如果文章对你有帮助,记得一键三连❤

    展开全文
  • 对象模板类(基类)和c#手动回收

    千次阅读 2022-03-24 17:03:32
    在一款游戏中,我们不止有一个对象池,为了方便对对象池的创建,由此写了一个模板类。当然,也可以实现全功能的对象池,不管什么类型都可以。在此就不在阐述了。 在此模板类中,使用了委托,系统自带的委托函数,...

    一、对象池
    在一款游戏中,我们不止有一个对象池,为了方便对对象池的创建,由此写了一个模板类。当然,也可以实现全功能的对象池,不管什么类型都可以。在此就不在阐述了。

    在此模板类中,使用了委托,系统自带的委托函数,以及堆栈的使用。

    using System.Collections.Generic;
    using UnityEngine.Events;
    using UnityEngine;
    
    public class ObjectPool<T> where T : new()
    {
    //最好改为只读的
        private   Stack<T> m_Stack = new Stack<T>(); //使用栈进行创建。
        private  UnityAction<T> m_ActionOnGet; 
        private   UnityAction<T> m_ActionOnRelease;
    
        public int countAll { get; private set; } 	//池中对象的总个数
        public int countActive { get { return countAll - countInactive; } }	//活跃的对象
        public int countInactive { get { return m_Stack.Count; } }	//失活的对象,即可以进行回收的对象
    
     	public T CreateObject()
        {
            T element;
            if (m_Stack.Count == 0)
            {
                element = new T();
                countAll++;
            }
            else
            {
                element = m_Stack.Pop();
            }
            if (m_ActionOnGet != null)
                m_ActionOnGet(element);
            return element;
        }
    
        public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease)  	
        {
            m_ActionOnGet = actionOnGet;
            m_ActionOnRelease = actionOnRelease;
        }
    
      
        public void Release(T element)
        {
            if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element))
            //输出错误日志,可以使用自己写的日志进行输出
                Debug.LogError("Internal error. Trying to destroy object that is already released to pool."); 	
            if (m_ActionOnRelease != null)
                m_ActionOnRelease(element);
            m_Stack.Push(element);	//弹栈
        }
    }
    
    
    

    二、C#手动回收
    在Net中,由GC垃圾回收线程掌握对象资源的释放,程序员无法掌控析构函数的调用时机。对于一些非托管资源,比如数据库链接对象等,需要实现IDisposable接口进行手动的垃圾回收。
    在此模板类中,使用了委托,系统自带的委托函数,以及堆栈的使用。

        
        //
        // 摘要:
        //     Defines a method to release allocated resources.
        [ComVisible(true)]
        public interface IDisposable
        {
            //
            // 摘要:
            //     Performs application-defined tasks associated with freeing, releasing, or resetting
            //     unmanaged resources.
            void Dispose();
        }
    
    
    展开全文
  • 什么是面向对象,以及什么是对象

    千次阅读 多人点赞 2019-08-11 19:04:04
    什么是面向对象,以及什么是对象 ​ 1.1面向过程与面向对象的区别 ​ 面向对象是一种现在最为流行的程序设计方法 。将面向过程与面向对象进行比较。 ​ 首先这两个种都是一种编程思维, 在一些简单的动作...
  • c++类模板用法讲解

    千次阅读 2018-06-19 23:56:15
    在编写类模板的程序时,把类模板的成员函数的声明和实现分别写在了头文件和源文件中,导致了出现编译出错的现象,现弄清楚了原因,特写此篇,供大家参考学习。c++中每一个对象所占用的空间大小,是在编译的时候就...
  • 类模板的实例是一个类对象类模板的每个实例就是一个类定义 这两句话到底哪个对啊![图片说明](http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/5.gif)![图片说明]...
  • C++ 函数模板&类模板详解

    千次阅读 多人点赞 2018-12-02 16:32:37
    在 C++ 中,模板分为函数模板和类...类模板是模板,模板类时具体的类 由函数模板实例化而得到的函数称为模板函数 由类模板实例化得到的类叫模板类   一.函数模板 函数模板的基本写法为:template &lt;typ...
  • C++函数模板与类模板的区别

    万次阅读 多人点赞 2018-07-18 16:54:55
    类模板: C++ 除了支持函数模板,还支持类模板(Class Template)。函数模板中定义的类型参数可以用在函数声明和函数定义中,类模板中定义的类型参数可以用在类声明和类实现中。类模板的目的同样是将数据的类型参数...
  • Python中的对象是什么

    千次阅读 2021-01-29 04:51:23
    一、面向过程和面向对象面向过程:根据业务逻辑从上到下写代码。面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复...(1)对象模板,例如:人类,是人这种生物的模板。(2)...
  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多...
  • C++:类模板与模板类的区别

    千次阅读 2020-07-08 17:39:35
    写在前面:(模板类是类模板实例化后的一个产物,类模板比作是一个作饺子的模子,而模板类就是用这个模子做出来的饺子,至于饺子什么馅儿的就需要你自己去实例化自己的内容。) 类模板:说明该类是一个模板,它代表...
  • 完整项目连接: 使用idea创建springboot项目_杨咩咩-CSDN博客创建一个以后都可以使用的springboot后台项目,放入git中托管,后期创建别的项目时,直接拖下来,修改完项目名和包名时直接使用...
  • C++类模板和模板类

    万次阅读 多人点赞 2018-11-29 14:32:35
    C++通过类模板来实现泛型支持。 1 基础的类模板 类模板,可以定义相同的操作,拥有不同数据类型的成员属性。 通常使用template来声明。告诉编译器,碰到T不要报错,表示一种泛型. 如下,声明一个普通的类模板: ...
  • c++中的类模板

    千次阅读 2021-07-20 00:04:50
    目录类模板模板类 类模板 同函数模板,大部分性质相同,类模板也用于代码的重用性体现,性质可见“函数模板” 定义格式: template <class NAME1,class NAME2,...> class class_name{ ///... }; 或 ...
  • C++之——类模板与函数模板用法

    千次阅读 2018-07-13 10:22:41
    模板是一种对类型进行参数化的工具; 通常有两种形式:函数模板和类模板; 函数模板针对仅参数类型不同的函数; 类模板针对仅数据成员和成员函数类型不同的类。 使用模板的目的就是能够让程序员编写与类型无关的代码...
  • 【C++入门】C++ 函数模板&类模板

    千次阅读 多人点赞 2021-02-10 09:52:27
    C++ 函数模板&类模板 主要内容 一、函数模板包括: 1.函数模板的定义 2.函数模板的实例化 3.函数模板的重载 4.函数模板和函数的次序 5.函数模板示例:Map 二、类模板包括: 1.类模板的定义 2.函数模版作为类模板成员...
  • C++中的类模板定义及实例化

    千次阅读 2019-08-21 13:44:08
    文章目录一、类模板定义及实例化定义一个类模板类模板实例化二、类模板的成员函数 一、类模板定义及实例化 定义一个类模板: template<class 模板参数表> class 类名{ // 类定义...... }; 其中...
  • 类模板的概念和意义

    千次阅读 2020-06-28 14:27:29
    类模板 存储和组织数据元素 类数据组织的方式和数据元素的具体类型无关 如:数组类,链表类,Stack类,队列类等 规则 类模板的应用 只能定义具体类型,无法自动推导 使用的具体类型定义对象 声明泛指类型T...
  • C++中模板类的静态成员

    千次阅读 2020-07-15 22:24:18
    模板类的静态成员和普通,普通函数的静态成员一样,我们想在函数调用后留些信息,而且这些信息随着函数调用的次数发生改变,也就说函数或者类对象执行完后,并没有完全消除而是留下了一下踪迹,比如:函数调用次数...
  • 什么是对象对象(Object)是一个应用系统中的用来描述客观事物的实体,是有特定属性和行为(方法)的基本运行单位。是的一个特殊状态下的实例。对象可以是一个实体、一个名词、一个可以...对象模板,它...
  • 类模板的使用~

    千次阅读 2018-06-04 11:52:07
    上一篇文章中是关于实习一个多功能计算器,计算表达式需要用到两个栈,一个存储...可用类模板来定义类,类模板是对象特性更为一般的抽象。简而言之,一个类模板就是一个抽象的类、类模板的一般定义形式为: ...
  • 链表(C++类模板实现)

    千次阅读 多人点赞 2020-07-30 20:43:47
    类模板这里有个坑就是无法分离编译,具体原因可以百度搜索类模板无法分离编译。最后废话不多说,直接上代码。 2. 代码     sqlist.h文件实现顺序表的声明和定义 #ifndef LINKLIST_H #define ...
  • 类模板三种类模板参数

    千次阅读 2018-04-22 10:40:47
    类模板三种类模板参数 实际上有三种类型模板参数:类型模板参数、模板模板参数(以模板作为模板的参数)、无类型模板参数。 &nbsp; 1、类型模板参数 类型模板参数是我们使用模板的主要目的。我们可以定义多个...
  • 一、类模板的定义: 类似函数模板,类模板以关键字template开始,后跟模板参数列表,即 <typename T, ...> 在类模板(及其成员函数)的定义中,我们将模板参数当作替身,代替使用模板时用户提供的类型或值。 ...
  • c++单例模式类模板的实现

    千次阅读 2017-08-20 18:37:49
    设计模式中的单例模式有懒汉单例模式和饿汉单例...(1) 将构造函数的访问属性设置为private,不让该中外部生成对象 (2) 将标志指针变量初始化为NULL (3) 当外部需要使用对象时,调用的静态成员函数,该函数判断
  • Java对象 详解(一)

    万次阅读 多人点赞 2016-10-06 20:48:02
    一、面向对象简述面向对象是一种现在最为流行的程序设计方法,几乎现在的所有应用都以面向对象为主了,最早的面向对象的概念实际上是由IBM提出的,在70年代的Smaltalk语言之中进行了应用,后来根据面向对象的设计...
  • C++之类模板特化

    千次阅读 2018-07-13 15:47:11
    C++之类模板特化 模板: template&lt;typename T1, typename T2&gt; class example{ public: example(); ~example(); private: T1 data1; T2 data2; int data3; }; template&lt;typename T1, ...
  • C++动态数组类模板

    千次阅读 2019-04-21 17:15:05
    功能:实现动态数组类模板 示例运行结果: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 -------------------------- Author: Zhang Kaizhou Date: 2019-4-21 17:19:00 -------------------------*/ #include &...
  • C++ 类模板和模板类

    万次阅读 2015-12-28 20:16:45
    类模板的意义和函数模板的意义是一样的。 类模板的定义 template //声明一个模板,虚拟类型名为T。注意:这里没有分号。 class Compare //类模板名为Compare { public : Compare(T a,T b) { x=a;y=b; } T max( ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 508,855
精华内容 203,542
关键字:

对象是类的模板