zoukankan      html  css  js  c++  java
  • UVW源码漫谈(四)

    十一假期后就有点懒散,好长时间都没想起来写东西了。另外最近在打LOL的S赛。接触LOL时间不长,虽然平时玩的比较少,水平也相当菜,但是像这种大型的赛事有时间还是不会错过的。主要能够感受到选手们对竞技的激情,对瞬息万变的战局的应变,非常精彩。KeKe~~。

    这一篇主要对UVW的源码讨论来收个尾,就介绍一下项目中其他的一些好玩的东西,稍微丰富一下知识。

    1、模版

    之前说了很多东西,但是都把它给忽略了,对于C++的模版,很多人对此有看法,说它难以理解,编写困难等等。

    我们都知道,模版也是C++多态的一种,属于编译期多态,也就是说C++把很多运行期的工作加到编译期了,你的代码保持了在语言层面的抽象层次。然而实际上编译器在编译时却对同类型模版的使用进行了特化。所以相比较运行时的多态,模版的运行性能是更好的,但是编译的时间可能就稍长了一些。

    虽然那些对模版的看法都讲的过去,但是模版在应用中所带来的作用是相当大的。举一个最简单的例子:

    std::shared_ptr<uvw::TcpHandle> tcp = loop.resource<uvw::TcpHandle>();

    这是我们项目中一个创建TcpHandle的语句,如果我们按照一般C的思路,写出来的代码很可能是这样的:

    TcpHandle* tcp = loop.resource(type);

     OK,看上去很正常,但是暴露了很多问题,这个resource函数的原型应该是:

    void* loop::resource(int type); 或者 Handle* loop::resource(int type);

    它肯定是返回void*或者Handle这个基类的指针,但是你只能通过你对代码的理解和type的值来判定,它返回的是TcpHandle*类型。万一我不小心把返回类型写成了UdpHandle*,它同样继承自Handle类,C++是没有对此的检测的。那这时候模版的价值就显示出来了,它可以直接根据模版的类型,对返回的类型起到限制作用。避免了上面情况的出现。

    再比如我们在 第二篇 中讲static的时候,没有模版就不能实现那样的功能。

    有些朋友在编码的时候很少或者根本就不用模版,顶多在用一些容器的时候。或许因为就算用模版,也会造成上面提到的一些负面影响。所以很多人知道模版,但是不常使用,不常使用的东西往往也会忘的非常快,造成这样一个不好的循环。如果模版可以解决切实的编码问题,大胆一点用就是了,不要怕用错,错了才能更好的用嘛!

    2、enum 

    enum就是枚举类型,但是C++11对enum有扩展。先看这段代码:

    fs.hpp  55 ~ 69

    enum class UVDirentTypeT: std::underlying_type_t<uv_dirent_type_t> {
         UNKNOWN = UV_DIRENT_UNKNOWN,
         FILE = UV_DIRENT_FILE,    
          。。。。。。
     };
    
    enum class UVCopyFileFlags: int {
        EXCL = UV_FS_COPYFILE_EXCL
    };

    enum和enum class的区别,有下面几点:

    1、如果在同一个头文件中,有下面的代码:

    1 enum HandleType{TCP,UDP,POLL,FS};
    2 enum StreamType{TCP,UDP,POLL,FS};

     这是编译不通过的,因为本身enum就相当于 #define 的一个集合,名字是不能一样的。但是用 enum class 来写,则是OK的,比如:

    1 enum class HandleType{TCP,UDP,POLL,FS};
    2 enum class StreamType{TCP,UDP,POLL,FS};

    但是使用的时候是需要加上作用域的。

    2、我们都知道enum中的每个元素都是可以直接转为int型的(对于不同的编译器,可能类型不一样)。但是 enum class 是不可以的。比如:

    1 enum HandleType{TCP,UDP,POLL,FS};
    2 enum class StreamType{TCP,UDP,POLL,FS};
    3 
    4 int handleType = TCP;
    5 int streanType = StreamType::TCP;    //错误

    第5行就会产生编译错误,enum很容易被隐式的转为int,在某种意义上,是enum的一种缺陷,所以enum class解决了这个问题.

    另外enum class的元素是可以指定类型的,比如:

     1 enum smallenum: int16_t
     2 {
     3     a,
     4     b,
     5     c
     6 };
     7 
     8 enum class altitude: char
     9 { 
    10      high='h',
    11      low='l', 
    12 };

    可以看到,这个 enum class中的 “class” 是可以省略的。那如果我有需求,要将enum class转为需要的类型怎么办?比如上面的两个例子,可以这样搞:

    1 smallenum s = smallenum::a;
    2 int16_t i = static_cast<int16_t>(s);
    3 
    4 altitude e = altitude::high;
    5 char c = static_cast<char>(e);

    当然,在switch 。。。 case。。。语句中是可以直接用的。

    最后

    到这里源码中关于语法一类的、使用的一些技术和方法就介绍到这里。这些东西其实也不难,也许大家都知道,不知道的通过介绍也有一些了解了,主要是让大家在看源码的时候可以舒服点,排除一些障碍。

    有些看官可能对项目中的代码的书写形式,使用方式等很多东西不是很习惯,但是我想说这应该就是现代C++的一个编码模式。你可能在一个项目中看不见一个指针,看不见一个强转,使用大量的模版,使用很多限制关键字,类实现和定义放在同一个文件,如同java一般,还有其他很多看不习惯的地方。但是当你熟悉了,明白了,习惯了,说不定效率就上升了。其实这些说到底还是要提升对C++的认知。

    之后我会再找一些在比较好的项目来和大家分享,比如架构,算法等方面的。由于水平有限,博客中若有错误,烦请指正。

  • 相关阅读:
    拼linq 时网上整理的一个类
    ASP.NET MVC controller 之间传JS值
    javascript 事件的一点感悟
    C#扩展特性
    javascript对json对象的序列化与反序列化
    javascript序列化json 第二篇
    单列模式
    Foreach 原理
    浅浅一谈 设计模式
    CRC循环冗余校验码总结(转)
  • 原文地址:https://www.cnblogs.com/yxfangcs/p/7709223.html
Copyright © 2011-2022 走看看