VBA类之一(初识类)

第一章 开头篇
                                ——认识类



       Visual Basic是基于对象的编程(注:本文所有的代码和讨论将都以VB为基础模型,不过我会尽量使用一些大家在VBA中常见的例子来做说明的。),所以我们常见的一些东西其实都与类有关。不需惊讶,是的,类其实离我们很近,它们正和我们天天相处。可以夸张的说,如果离开了类,我们的VB(VBA)就无用武之地了。
        我们还是先来看一条非常简单的语句,让我们亲身体会一下类与我们的距离:

  1.  
  2. '例一
  3. Sub Hello()
  4.   Range("A1").Value = "Hello,world"
  5. End Sub

复制代码


        我们就暂且称之为VBA的Hello world吧,看到这个简单到不能再简单的例子,或许你笑了,这个根本就和类没有关系嘛。是的,我们在这里并没有明显的看到类,但是我们看到了Range("A1")这个对象,而在Range("A1")前面,还隐藏着一个对象:ActiveSheet,而在ActiveSheet前面又有一个ActiveWorkbook,而在ActiveWorkbook前面还有一个Application。是的,这些都是对象,我们依旧没有看到类。先别急,我们再从后面往前面看一遍:Range("A1").Value="Hello,World"   Value是什么?Value是一个Range("A1")这个对象的一个属性。那它是从哪来的呢?它是由Range类定义的,是的,我们发现了第一个出现在我们的面前的类 Range。你或许一下还接受不了,你刚刚在前不是还说Range("A1")是一个对象吗?怎么现在又说Range又是一个类呢。呵呵,不着急,我们还是看看下面的这个例子,或许你就很快就会明白了。

  1.  
  2. '例二
  3. Sub Hello()
  4.   Dim Range1 As Range             '引用一个Range类
  5.   Set Range1 = Range("A1")       '将类实例化
  6.   Range1.Value = "Hello,world"   '这时,Range1又是一个对象了
  7.   Set Range1 = Nothing                '销毁一个类的实例
  8. End Sub

复制代码

       或许你现在已经发现了,我们引用了一个Range类,并将之实例化后修改了它的属性。而在例一中,我们只不过是将这一切都以隐藏起来,直接对一个对象Range("A1")修改它的属性,但Range("A1")这个对象正是引用了Ragne这个类,才具有了Range类的属性"Value"。类本身并不直接为我们做什么,但是,它却又一直默默的隐藏在幕后规化着我们的动作。是的,这就是类,它往往都是通过对象的方式展现在我们的面前,让我们无时无刻与之交流,却又常常在不经意间忽视了它的存在。现在再回到例一去看,就会很容易的发现,ActiveSheet实际引用了Worksheet类、ActiveWorkbook引用了Workbook类,而Application则引用了和它同名的Application类(这也正是我们会经常被混淆一个概念,一个对象可以和被它所引用的类同名),原来我们在短短一个赋值的语句中,已经在与这么多的类打交道。
        类就像是我们呼吸的空气,我们一直深在其中,却又常常忘却了它的存在。那我们又要怎样来区分类和对象呢?其实它们经常成对的出现在我们面前,只是一个看得见摸得着的,一个却深藏不露。我们可以这样去理解类与对象:类是一个概念或是一种定义,每个类拥有其自己的特征和行为方式,而对象就是某个类的实例。就像"人","人"是一个定义,你一看到"人"就会想到它是直立行走、有头、五官……等各种特征,但当"人"被具体到你、我、或是某一个人的时候,它就是一个对象了。
        既然类与我们和程序息息相关,那么我们更应该去好好的了解它了。让我们准备好行囊,到神秘的类的领地去好好浏览一番吧。


第二篇 走近类
                                ——类的基本写法及注意项



        如果说上一篇让我们看到类隐藏在神秘面纱后的面孔,那么现在我们将要做的就是真正的看清楚它。不过,在此之前我还是要让大家再次熟悉一下面的几个关键词:

Public                外部,可供类或是模块自身外调用;
Private               内部,只能由类或是模块内部直接调用;
Friend                友元,只能由工程内调用(即:在当前工程内部调用时相当于Public,而对外部工程相当于Private。)。
SubFunction  过程(不返回值)和函数(返回值),在类中我们可将其视为类的方法;
Property Get      返回属性的值;
Property Let      设置属性的值;
Property Set      设置对象属性的值(即:该属性含有对象引用)。
        [注:Property往往是成双出现在类中的某一个属性上,甚至可能三者同时出现,当一个类中某个属性只有Property Get时代表这一属性为只读属性,比如在VB工程中Form类的hWnd属性。]
Event           定义用户自定义的事件
        [注:Event可以像声明过程的参数一样来声明事件的参数,但有以下不同:事件不能有带命名参数、Optional 参数、或者 ParamArray参数。事件没有返回值。];
RaiseEvent      引发在一个类、窗体、或者文档中的模块级中声明的一个事件。
Implements      指定要在包含该语句的类模块中实现的接口或类。


       当我们熟悉上面的几个关键词后,再来分析类,就会发现类其实也挺简单。我们将从一个简单的类开始来正式的学习类的定义和使用方法。不过在此之前,我建议大家先去读读qee用兄写的一个帖子:VBA类:隐者的秘密qee用兄在那个帖子中图文并茂,已经将类清晰的描绘出来,并亲自带领我们写了一个类。在此,让我们向qee用兄道声辛苦,并送上万分感激。好了,现在,我们来写一个非常简单的类,用它来实现两个数的四则运算。

  1.  
  2. '类的名称定义为:四则运算
  3. Option Explicit
  4.  
  5. Public Event OnError(ByVal Number As Long, ByVal Description As String, ByVal Source As String)
  6.  
  7. Private lNum1 As Double, lNum2 As Double
  8.  
  9. Public Property Let Number1(ByVal Number As Double)
  10.   lNum1 = Number
  11. End Property
  12.  
  13. Public Property Get Number1() As Double
  14.   Number1 = lNum1
  15. End Property
  16.  
  17. Public Property Let Number2(ByVal Number As Double)
  18.   lNum2 = Number
  19. End Property
  20.  
  21. Public Property Get Number2() As Double
  22.   Number2 = lNum2
  23. End Property
  24.  
  25. Public Property Get 和() As Double
  26.  
  27.   On Error GoTo Error01
  28.   
  29.   和 = lNum1 + lNum2
  30.   Exit Property
  31. Error01:
  32.   RaiseEvent OnError(Err.Number, Err.Description, Err.Source)
  33.   Err.Clear
  34.   和 = 0
  35. End Property
  36.  
  37. Public Property Get 差() As Double
  38.  
  39.   On Error GoTo Error02
  40.   
  41.   差 = lNum1 - lNum2
  42.   Exit Property
  43. Error02:
  44.   RaiseEvent OnError(Err.Number, Err.Description, Err.Source)
  45.   Err.Clear
  46.   差 = 0
  47. End Property
  48.  
  49. Public Property Get 积() As Double
  50.  
  51.   On Error GoTo Error03
  52.   
  53.   积 = lNum1 * lNum2
  54.   Exit Property
  55. Error03:
  56.   RaiseEvent OnError(Err.Number, Err.Description, Err.Source)
  57.   Err.Clear
  58.   积 = 0
  59. End Property
  60.  
  61. Public Property Get 商() As Double
  62.  
  63.   On Error GoTo Error04
  64.   
  65.   商 = lNum1 / lNum2
  66.   Exit Property
  67. Error04:
  68.   RaiseEvent OnError(Err.Number, Err.Description, Err.Source)
  69.   Err.Clear
  70.   商 = 0
  71. End Property
  72.  
  73. Public Sub ClearNumber()
  74.   lNum1 = 0: lNum2 = 0
  75. End Sub

复制代码

       然后,将下面的代码写到ThisWorkbook模块中:

  1.  
  2. Option Explicit
  3.  
  4. Private WithEvents Class1 As 四则运算
  5.  
  6. Sub TestClass()
  7.   If Class1 Is Nothing Then Set Class1 = New 四则运算
  8.   Class1.ClearNumber
  9.   Class1.Number1 = 9
  10. '  Class1.Number2 = 8
  11.   Debug.Print Class1.和
  12.   Debug.Print Class1.差
  13.   Debug.Print Class1.积
  14.   Debug.Print Class1.商
  15. End Sub
  16.  
  17. Private Sub Class1_OnError(ByVal Number As Long, ByVal Description As String, ByVal Source As String)
  18.   MsgBox "类中发生错误,错误代码:" & Number & " 错误提示:" & Description & " 错误源:" & Source
  19. End Sub

复制代码

       这是一个非常简单的类的定义和应用(当然,实际编程时很少有人会为了四则运算而专门写个类。),虽然它很简单,不过它却几乎包含了类所有常见的特征:属性、方法、事件。运行TestClass后我们可以看到立即窗口中的输出,并接收到一个MsgBox的窗体,它提示了我们在类运行过程中产生了一个除数为零的错误,而这正是类中的OnError事件激发的。
       虽然这个类本身没有什么实际的应用的意义,但是我们却可以用它来做一个模版,我们只要参照这个类,就可以很快的写出自己想要的类。
       你现在是不是已经有了自己马上要编写一个类的冲动呢?那么我们开始准备动手吧,不过在你动手之前,我这里还要给你几点关于类的建议(这些都是笔者自身积累的经验或是前辈们的忠告。):

       一、在正式编写一个类的前期,最好尽可能规定好所有要用到的接口与方法。一旦一个类被正式发行后(封装成DLL并被其它的工程引用),后期维护时尽量不要再去修改已有的接口函数及其参数,除非你打算将所有的工程全部重写;
       二、为你类中的属性、方法、事件取个有意义的名字(特别是声明为Public方式的),如果允许的话,最好使用“工具”->“过程属性”为其添加一些描叙,说明它的意义或是调用方式,这样可以方便查看其属性并让客户(甚至是自己)能很快明白这个函数的用途;
       三、只暴露必须的接口供外部调用,不要将一些可能仅在类内部使用属性和方法暴露给类外部;
       四、不到万不得已,不要在类中定义Public方式的变量;
       五、重新编译新版本的DLL时,最好是按“版本相同版本兼容版本不兼容”这个次序来选择编译后DLL版本兼容性,即:能用“版本相同”方式就不要用“版本兼容”,更不要用“版本不兼容”,因为“版本不兼容”方式就意味着你的旧工程在其重新编译前将无法使用这个DLL。一旦准备使用无兼容性版本,那么就要考虑如何减少部件的用户以后可能遇到的麻烦。如果以后的版本还要做一些可能破坏兼容性的修改,那么最好把这些修改集中在一次进行。计划对不兼容进行的修改时,把工程作为一个新的任务来对待,应该投入尽可能多的精力进行计划,就象在创建新的部件。创建不兼容版本,这要求三个步骤:改变工程名,改变文件名以及通过选定不兼容进行编译(注:这三个步骤最好是一定要做到,否则将会让我们在后面安装引用此类时会发生各种问题而导致我们无法使用类);
       六、可能的话,不要忘了在类内部添加错误处理过程,尽管这些错误处理过程可能会损耗我们的运行时间,但它们能让我们的类更健壮;
       七、类中不能定义Public方式的结构(Type),如果必需要这么做的话,可以使用一个类来代替Type
       八、在类的Class_Terminate()事件中释放被当前类所引用的类或是数据。当我们某个类的实例已经不再需要时,请将其使用 Set[I]Object[/I] = Nothing 的方式来销毁它;
       九、……(留给大家填吧)……








 


第三篇 为什么要使用类
                                ——类的作用及其重要性



       现在,我们已经初步的认识了类,甚至我们已经可以自己开始写自己的类了。但是我们却还不是很清楚,类给我们带来了什么?我们为什么要用类?我们就先来看看类的好处吧。
       1、代码重用;
       2、降低程序的藕合度; 
       3、增强程序的可拓展性;
       4、易修改性;
       5、……

       “藕合度”指的是程序模块间存在联系的紧密程度。如果一个程序各模块存在的联系太紧密时,就意味后期的修改将会非常复杂,甚至于有时为了修改某一个代码功能时可能要全部工程文件都修改一次,并且由于各模块间的函数与变量相互相交调用,严重的影响了程序的可读性。自然,我们不希望发生这种情况。而类正是我们规避这个情况发生的首选工具。因为类对于外部而言,我们所需要的仅仅是调用类的接口函数,而类内部的结构与运行我们并不需要去关心它。就像一个用来处理数据的类,我们只要约定好类的接口,就可以在外部直接获取或是修改我们想要的数据。但是数据存在哪,用什么方式或是结构组成我们根本就不需要了解,我们所要做的只是在外部直接调用就好了。这就意味着我们一旦约定好了接口,就可以同时开始开发前台与后台的数据处理块。而且,当我们需要修改数据的存储方式时,也会变得更加简单。比如:我们现有一个处理数据的类,它目前是使用文件来存储数据,现在我们需要把数据存储改为SQL数据库,这时我们要做的仅仅是在类内部修改要数据的处理过程,而对于整个工程而言,我们甚至不用做任何的修改就可以直接用了。这样对于大型工程而言,犹为重要,因为我们常常把类封装成DLL,这就意味我们仅仅只需要重新编译这个DLL,然后发布给用户升级就完成了这次修改,否则的话我们只能将整个工程全部修改后重新发布给用户才能使用。如果你经常使用VBA的话就一定会常常遇见Range这个类,Office每一次大版本升级,其内部的文件结构都会有变动,但是我们在VBA中对Range的操作却无需更改就可以直接使用了,这个正是因为Range类虽然内部改动了,但是它的接口还是一样,所以我们原有的VBA工程并不需要改动就可以直接使用了。
现在我们再来通过一个选中区域高亮显示的例子来看看类的其它几个特性吧:

  1.  
  2. Option Explicit
  3.  
  4. Private Type TypeRageLast
  5.   Range       As Range
  6.   ColorIndex  As Long
  7. End Type
  8.  
  9. Private Const ColorIndex = 5&
  10. Private RangeLast() As TypeRageLast
  11.  
  12. Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  13.   Dim I As Long
  14.   Dim Range1 As Range
  15.   
  16.   On Error Resume Next
  17.   If UBound(RangeLast) = -1 Then
  18.     ReDim RangeLast(0)
  19.   ElseIf UBound(RangeLast) Then
  20.     For I = 1 To UBound(RangeLast)
  21.       If RangeLast(I).Range.Interior.ColorIndex = ColorIndex Then
  22.         RangeLast(I).Range.Interior.ColorIndex = RangeLast(I).ColorIndex
  23.       End If
  24.     Next I
  25.   End If
  26.   
  27.   I = 0
  28.   ReDim RangeLast(0)
  29.   
  30.   For Each Range1 In Target
  31.     I = I + 1: ReDim Preserve RangeLast(I)
  32.     RangeLast(I).ColorIndex = Range1.Interior.ColorIndex
  33.     Set RangeLast(I).Range = Range1    
  34.   Next Range1
  35.   Target.Interior.ColorIndex = ColorIndex
  36. End Sub

复制代码

这段代码的功能很简单(我们在这里并不去讨论它的功能),只是在工作表中,选中某个区域后就把该区域的背景色设置为并且恢复上次被选中区域的原有背景色。我们只要把上面的代码拷贝到我们需要的工作表的代码中就可以实现这个功能了。但是,当我在实际使用过程中就会发现一些新的问题:
       1、如果我们的工作簿中有200个工作表需要这个功能,我们就要复制200次——晕倒……
       2、复制完200次后,我们再在各个工作表中实际测试一下。就会发现新的问题:当我们在各个工作表之间切换焦点时,原工作表中最后一次被高亮的区域没有被还原!现在我们需要修改代码——在每一个工作表中Deactivate事件中加上相应处理代码。天啊,又得200次……又要晕了吧?
       3、文档开始正式使用了,但是当我们新增一个工作表后发现:我们又得重新切换到VBA中再复制一次代码!如果这个文档是给客户使用的,难道我们还要要求客户每次增加工作表时自己去复制VBA代码?……这次彻底晕了吧?^_^
       难道就没有更方便的方法吗?

       当然有了。我们就用类来试试吧,我们先建一个clsSelHeightColor类:

  1.  
  2. ‘类名:clsSelHeightColor
  3. Option Explicit
  4.  
  5. Private Type TypeRageLast
  6.   Range       As Range
  7.   ColorIndex  As Long
  8. End Type
  9.  
  10. Private Const ColorIndex = 5&
  11. Private WithEvents mSheet As Worksheet
  12. Private WithEvents Workbook  As Workbook
  13. Private RangeLast() As TypeRageLast
  14.  
  15. Private Sub mSheet_Activate()
  16.   Dim I As Long
  17.   Dim Range1 As Range
  18.   
  19.   On Error Resume Next
  20.   I = 0
  21.   ReDim RangeLast(0)
  22.   
  23.   For Each Range1 In Selection
  24.     I = I + 1: ReDim Preserve RangeLast(I)
  25.     RangeLast(I).ColorIndex = Range1.Interior.ColorIndex
  26.     Set RangeLast(I).Range = Range1
  27.     Range1.Interior.ColorIndex = ColorIndex
  28.   Next Range1
  29. End Sub
  30.  
  31. Private Sub mSheet_Deactivate()
  32.   mSheet_SelectionChange Nothing
  33. End Sub
  34.  
  35. Private Sub mSheet_SelectionChange(ByVal Target As Range)
  36.   Dim I As Long
  37.   Dim Range1 As Range
  38.   
  39.   On Error Resume Next
  40.   
  41.   If UBound(RangeLast) Then
  42.     For I = 1 To UBound(RangeLast)
  43.       If RangeLast(I).Range.Interior.ColorIndex = ColorIndex Then
  44.         RangeLast(I).Range.Interior.ColorIndex = RangeLast(I).ColorIndex
  45.       End If
  46.     Next I
  47.   End If
  48.   
  49.   I = 0
  50.   ReDim RangeLast(0)
  51.   
  52.   For Each Range1 In Target
  53.     I = I + 1: ReDim Preserve RangeLast(I)
  54.     RangeLast(I).ColorIndex = Range1.Interior.ColorIndex
  55.     Set RangeLast(I).Range = Range1
  56.   Next Range1
  57.   Target.Interior.ColorIndex = ColorIndex
  58. End Sub
  59.  
  60. Public Property Set Sheet(ByVal mSheet1 As Worksheet)
  61.   If Not (mSheet Is Nothing) Then mSheet_SelectionChange Nothing
  62.   Set mSheet = mSheet1
  63.   Call mSheet_Activate
  64. End Property
  65.  
  66. Public Property Get Sheet() As Worksheet
  67.   Set Sheet = mSheet
  68. End Property
  69.  
  70. Private Sub Class_Initialize()
  71.   ReDim RangeLast(0)
  72. End Sub
  73.  
  74. Private Sub Class_Terminate()
  75.   mSheet_SelectionChange Nothing
  76.   Erase RangeLast
  77. End Sub

复制代码

然后再把下面的代码复制到ThisWorkbook中的代码框中:

  1.  
  2. Option Explicit
  3.  
  4. Dim mSheets As Collection
  5.  
  6. Private Sub Workbook_BeforeClose(Cancel As Boolean)
  7.   Set mSheets = Nothing
  8. End Sub
  9.  
  10. Private Sub Workbook_NewSheet(ByVal Sh As Object)
  11.   Dim clsSheet As New clsSelHeightColor
  12.   
  13.   Set clsSheet.Sheet = Sh
  14.   mSheets.Add clsSheet
  15.   Set clsSheet = Nothing
  16. End Sub
  17.  
  18. Private Sub WorkBook_Open()
  19.   Dim clsSheet As clsSelHeightColor
  20.   Dim Sheet As Worksheet
  21.   
  22.   On Error Resume Next
  23.   
  24.   Set mSheets = New Collection
  25.   For Each Sheet In Sheets
  26.       Set clsSheet = New clsSelHeightColor
  27.       Set clsSheet.Sheet = Sheet
  28.       mSheets.Add clsSheet
  29.       Set clsSheet = Nothing
  30.   Next
  31. End Sub

复制代码

保存后重开工作簿测试……嘿嘿,全部搞定!而且当我们要增加的Deactivate事件中的代码仅仅只需类中添加一次,只有一行代码(上面的类中已经添加好了),方便吧?当我们新增工作表时,也不再需要去复制一次代码了,一行代码都不用写了就已经实现了这个功能。当其它工作簿也需要这个代码时,我们只要在ThisWorkbook代码中增加相应的代码,并导入这个类就行了,比一个一个表去复制代码方便多——一想到相同的代码要在每个工作表中复制一次就头晕了。
       在此,我们对类的功能和特性有了一定的了解,不过,还有更多的东西在等待我们去发现。当下面向对象编程如此风行,类在其中的功劳是无与伦比的。
       现在,还犹豫什么?快去和类做一次“0距离接触”吧……

       在此,此文也终于要作一个小小的终结了。大家也跟随我初步对类作了点了解,也算是对类有了个第一印象吧。当然,类的高级应用和复杂型的类我们并没有去了解,或许哪天你会引领我去浏览一番?
       我也谢谢大家浪费不少时间来看完这个帖子,如果对我有意见或是觉得我在胡说八道要拍我砖头的,请下手留点情——我很怕疼,有意见扔扔鸡蛋或是RMB就好了。如果觉得看完对你有所帮助的话就帮顶下吧,或是你看完有什么问题的话也可以直接问,只要我会的我一定回(太难的问题还请恕我无能为力)。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439562.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HDU - 5009】Paint Pearls(dp,链表优化dp)

题干: Lee has a string of n pearls. In the beginning, all the pearls have no color. He plans to color the pearls to make it more fascinating. He drew his ideal pattern of the string on a paper and asks for your help. In each operation, he sele…

动手学无人驾驶(7):车道线检测

最近在研究视觉语义地图,需要进行车道线检测,发现这篇车道线检测论文效果蛮好的 (Ultra Fast Structure-aware Deep Lane Detection)。论文作者在知乎上已经介绍过了:https://zhuanlan.zhihu.com/p/157530787&#xff…

Coursera自动驾驶课程第16讲:LIDAR Sensing

在第15讲《Coursera自动驾驶课程第15讲:GNSS and INS Sensing for Pose Estimation》 我们学习了自动驾驶定位中常用的两种传感器:IMU(惯性测量单元) 和GNSS(全球导航卫星系统)。 本讲我们将学习自动驾驶汽…

DB、ETL、DW、OLAP、DM、BI关系结构图

在此大概用口水话简单叙述一下他们几个概念: (1)DB/Database/数据库——这里一般指的就是OLTP数据库,在线事物数据库,用来支持生产的,比如超市的买卖系统。DB保留的是数据信息的最新状态,只有一…

Tarjan 算法 常用模板

可以求每个点属于第几个强连通分量&#xff1a;https://blog.csdn.net/dellaserss/article/details/8267192 int Tarjan(int u){int v;dfn[u]low[u]Index;stack[Top]u;Instack[u]1;for(int i0;i<G[u].size();i){vG[u][i];if(!dfn[v]){Tarjan(v);low[u]min(low[u],low[v]);}…

【HDU - 5012】Dice(模拟,bfs)

题干&#xff1a; There are 2 special dices on the table. On each face of the dice, a distinct number was written. Consider a 1.a 2,a 3,a 4,a 5,a 6 to be numbers written on top face, bottom face, left face, right face, front face and back face of dice A. S…

重读经典:《Generative Adversarial Nets》

GAN论文逐段精读【论文精读】这是李沐博士论文精读的第五篇论文&#xff0c;这次精读的论文是 GAN。目前谷歌学术显示其被引用数已经达到了37000。GAN 应该是机器学习过去五年上头条次数最多的工作&#xff0c;例如抖音里面生成人物卡通头像&#xff0c;人脸互换以及自动驾驶中…

一步步编写操作系统 62 函数调用约定

由于我们要将c语言和汇编语言结合编程啦&#xff0c;所以一定会存在汇编代码和c代码相互调用的问题&#xff0c;有些事情还是要提前交待给大家的&#xff0c;本节就是要给大家说下函数调用规约中的那些事儿。 函数调用约定是什么&#xff1f; 调用约定&#xff0c;calling co…

重读经典:《An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale》

ViT论文逐段精读【论文精读】这次李沐博士邀请了亚马逊计算机视觉专家朱毅博士来精读 Vision Transformer&#xff08;ViT&#xff09;&#xff0c;强烈推荐大家去看本次的论文精读视频。朱毅博士讲解的很详细&#xff0c;几乎是逐词逐句地讲解&#xff0c;在讲解时把 ViT 相关…

【Gym - 101612C】【2017-2018NEERC】Consonant Fencity(状压枚举,预处理)

题干&#xff1a; 把26个字母分成19个辅音字母和7个元音字母&#xff0c;让你通过 将某些字母改为大写状态&#xff0c;使得字符串中连续的两个大小写状态不同的辅音字母组成的字母对数量最多&#xff0c;输出该状态下的字符串。注意输出的字符串中同一字母必须形态统一&#…

浅谈Mysql 表设计规范

本文首先探讨下数据库设计的三大范式&#xff0c;因为范式只是给出了数据库设计的原则&#xff0c;并没有告诉我们实际操作中应该怎样操作&#xff0c;应该注意什么&#xff0c;所以我们还会谈下实际工作中需要注意的具体操作问题。 三大范式 首先放出三大范式内容&#xff0c…

从零开始学视觉Transformer(1):Hello Vision Transformer

Vision Transformer打卡营分享一门很棒的 ViT 课程&#xff0c;课程详细介绍可以看这篇文章&#xff1a; 《Vision Transformer打卡营来啦&#xff01;朱欤博士带你从零玩转ViT爆款模型&#xff01;》

SQLServer中ISNULL、NULLIF和CONVERT函数

效率&#xff1a; UNION和UNION ALL关键字都是将两个结果集合并为一个&#xff0c;但这两者从使用和效率上来说都有所不同。 1、对重复结果的处理&#xff1a;UNION在进行表链接后会筛选掉重复的记录&#xff0c;Union All不会去除重复记录。 2、对排序的处理&#xff1a;Union…

一步步编写操作系统 66 浅析c库函数与系统调用1

本来说好的接下来的工作是要去“丰满”我们的内核&#xff0c;可咱们这种一步一回头的学习方式还得继续啊。其实我了解大家急切写内核的心情&#xff0c;但本书《操作系统真象还原》&#xff08;请大家支持正版&#xff09;的目的不是写一个操作系统就完事了&#xff0c;而是让…

给不会调用C++STL库中二分函数lower_bound,upper_bound,binary_search同学的一些话!

lower_bound算法返回第一个大于等于给定值所在的位置。设置两个指针start和last&#xff0c;其中start指向数组的起始位置&#xff0c;last指向数组末尾位置之后的位置。当start和last指向相同位置时循环结束。mid指向[start,last)区间的中间位置&#xff0c;当中间位置元素值大…

详解IMU标定经典论文:A Robust and Easy to Implement Method for IMU Calibration without External Equipments

本文介绍一篇 关于IMU 标定的经典论文&#xff0c;论文收录于 ICRA14&#xff0c;在论文中作者介绍了如何不适用外部设备标定 IMU 加速度和角速度偏差、尺度系数、轴偏移参数。 论文链接&#xff1a;https://readpaper.com/paper/2021503353、https://readpaper.com/paper/221…

重读经典:《Momentum Contrast for Unsupervised Visual Representation Learning》

MoCo 论文逐段精读【论文精读】这次论文精读李沐博士继续邀请了亚马逊计算机视觉专家朱毅博士来精读 Momentum Contrast&#xff08;MoCo)&#xff0c;强烈推荐大家去看本次的论文精读视频。朱毅博士和上次一样讲解地非常详细&#xff0c;几乎是逐词逐句地讲解&#xff0c;在讲…