<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C++繼任者?Carbon語法速覽!

          共 9808字,需瀏覽 20分鐘

           ·

          2022-08-01 04:15

          7月19日Cpp North大會上,谷歌的C++專家Chandler Carruth發(fā)表了『C++: What Comes Next? (Announcing the Carbon Language experiment) 』的主題演講,官宣了正在實驗中的Carbon語言,其目標是成為C++的繼任者。該消息迅速火爆全球,中文互聯(lián)網(wǎng)圈在7月20號也開始大量報道這一消息。

          Chandler Carruth在谷歌負責LLVM編譯器的優(yōu)化,也是谷歌在 C++ 委員會的代表。

          目前Carbon語言在Github上已經(jīng)開源,地址:https://github.com/carbon-language/carbon-lang

          7月22日,Cpp North的Youtube頻道公開了這一演講的視頻:https://www.youtube.com/watch?v=omrY53kbVoA&ab_channel=CppNorth

          接下來讓我們來速覽一下Carbon的語法,首先聲明本文的Carbon代碼都是基于Chandler Carruth的Keynote以及當前Carbon的github倉庫中的代碼。

          由于Carbon還在實驗階段,Chandler Carruth的Keynote中演示某些語法,當前的Carbon還不支持編譯……,比如abstract class、類外定義函數(shù)等等。當然已經(jīng)實現(xiàn)的語法部分可能不穩(wěn)定,后期也可能會再有重大調(diào)整也未可知。

          由于當下并且沒有支持Carbon語法的代碼高亮插件,所以下面代碼中的高亮并不準,敬請見諒。

          Hello World

          package ExplorerTest api;

          第一行是定義了package(包),包名是ExplorerTest。后面的api,那個不是包名的一部分,但是又不能省略(當前可以是api或impl)。

          fn Main() -> i32 {
            var s: auto = "Hello world!";
            Print(s);
            return 0;
          }

          定義了main函數(shù),Carbon中使用的Main()。從這個Hello World的例子中,變量語法、函數(shù)定義語法可見一斑。

          變量

          var

          即變量:

          var x: i64 = 42;
          x = 7;

          筆者點評:個人感覺還不如C++的語法簡潔…… int64_t x = 42;

          冒號后面是變量的類型,i64是int64,也可以使用auto做類型推導:

          var x: auto = 42;

          let

          基本等同于C++中常量,Rust也采用let表示常量。

          let x: i64 = 42;

          同樣也支持auto

          let x: auto = 42;

          控制流

          if else

          if (fruit.IsYellow()) {
            Console.Print("Banana!");
          else if (fruit.IsOrange()) {
            Console.Print("Orange!");
          else {
            Console.Print("Vegetable!");
          }

          和C/C++一樣。

          while

          var x: i32 = 0;
          while (x < 3) {
            Console.Print(x);
            ++x;
          }
          Console.Print("Done!");

          也和C++一樣

          for

          for (var step: Step in steps) {
            if (step.IsManual()) {
              Console.Print("Reached manual step!");
              break;
            }
            if (step.NotReady()) {
              continue;
            }
            step.Process();
          }

          語法是for-range循環(huán)的語法。同樣也能發(fā)現(xiàn)Carbon支持break和continue。

          match

          Carbon中沒有switch,但是有match:

          fn Bar() -> (i32, (f32, f32));

          fn Foo() -> f32 {
            match (Bar()) {
              case (42, (x: f32, y: f32)) => {
                return x - y;
              }
              case (p: i32, (x: f32, _: f32)) if (p < 13) => {
                return p * x;
              }
              case (p: i32, _: auto) if (p > 3) => {
                return p * Pi;
              }
              default => {
                return Pi;
              }
            }
          }

          不過C++中的switch能比較的只能是整型、枚舉。

          函數(shù)

          fn Add(a: i64, b: i64) -> i64 {
            return a + b;
          }

          Carbon中這個Add函數(shù)的寫法和Rust中實現(xiàn)一個Add幾乎一模一樣。比如聲明參數(shù)的時候類型在后,并且冒號分割的參數(shù)寫法。還有fn關鍵字。

          當然在函數(shù)體內(nèi)邏輯復雜的時候,會和Rust不同,因為Rust還有不帶分號的表達式語法,表達式的值就是整個函數(shù)的值。Carbon沒有那種怪異的東西。

          另外Carbon也能進行返回值的類型推導:

          fn Add(a: i64, b: i64) -> auto {
            return a + b;
          }

          一個更復雜的函數(shù)的例子:

          package Geometry api;

          import Math; // 導入其他包

          class Circle { // 定義一個Circle類
              var r: f32;
          }

          fn ScaleAreaAndAppend(circle: Circle, log2_scale: i32,
                                results: Vector(f32)*) {
            var area: f32 = Math.Pi * c.r * c.r;
            let scale: i32 = 1 << log2_scale;
            area *= scale;
            results->append(area);
          }

          參數(shù)默認都是常量,除非聲明成指針類型。

          面向?qū)ο?/span>

          類與對象

          class Point {
            var x: i32;
            var y: i32;
          }
           
          fn Main() -> i32 {
            var p1: Point = {.x = 1, .y = 2}; 
            var p2: auto = p1; 
            p2.x = 3;
            return p1.x - 1;
          }

          成員變量與成員函數(shù)

          class NewsAriticle {
            // 類似C++的static
            fn Make(headline: String, body_html: String) -> NewsAritcle();

            // 只讀方法
            fn AsHtml[meSelf]() -> String;

            // 可修改方法
            fn Publish[addr meSelf*]() { me->published = DateTime.Now(); }

            private var headline: String;
            private var body_html: String;
            private var published: Optional(Datetime);
          }
          // 類外定義成員函數(shù)
          fn NewsAriticle.AsHtml[meSelf]() -> String{ ... }

          Carbon中類中成員訪問控制權限默認都是public,如果需要聲明成私有則需要單獨加private關鍵字。這個行為和C/C++的struct相同,但是和主流語言的class都不同。

          定義在類中的函數(shù),如果有[me: Self]表示是只讀的成員函數(shù),在函數(shù)中不能修改類對象的成員變量。me在函數(shù)體中是表示對當前對象的引用,類似C++的(*this)

          如果有[addr me: Self*]表示的是可對當前對象進行修改的函數(shù)。me在函數(shù)體中類似C++的this指針。

          [me: Self][addr me: Self*]的成員函數(shù),也可以稱作方法(method),如果類中的函數(shù)沒有[me: Self][addr me: Self*],則表示是一個和對象無關的函數(shù),等價于C++中的static成員函數(shù)。這個設計很像python中的類中成員函數(shù)的設計。

          繼承與抽象

          Carbon只支持單繼承,這沒的說。值得注意的是普通的class關鍵字定義的類型默認都是final的,即不能被繼承生成子類(俗稱『絕育』)。但abstrct classbase class關鍵字定義的類型可以被繼承:

          // 抽象類(abstract class)不能被實例化,因為其中可能包含抽象方法
          abstract class UIWidget {
            // 抽象方法(abstract fn)沒有實現(xiàn)
            abstract fn Draw[meSelf](s: Screen);
            abstract fn Click[addr meSelf*](x: i32, y: i32);
          }

          // base class 允許擴展和實例化 
          base class Button extends UIWidget {
            // 實現(xiàn)抽象方法
            impl fn Draw[meSelf](s: Screen) { ... }
            impl fn Click[addr meSelf*];

            // 新增了一個虛函數(shù)(virtual fn
            virtual fn MoveTo[addr meSelf*]
          (x: i32, y: i32);
          }

          // 類外實現(xiàn)方法
          fn Button.Click[addr meSelf*](x: i32, y: i32) { ... }
          fn Button.MoveTo[addr meSelf*](x: i32, y: i32) { ... }

          class ImageButton extends Button {
            ...
          }

          abstrct class就是抽象類,它不能被實例化,因為其中有抽象方法。抽象類與抽象方法的概念和Java類似。抽象方法等同于C++中的純虛函數(shù)

          base class不僅是可以被繼承(擴展)的類,還能實例化。因為它里面不會有抽象方法,所有繼承而來的抽象方法都要被實現(xiàn)。base class中也能用virtual修飾成員函數(shù),這個語法是從C++中的虛函數(shù)而來的。

          泛型

          泛型接口

          定義泛型接口來做泛型代碼的類型檢查

          interface Summary {
            fn Summarize[meSelf]() -> String;
          }

          這個interface不是Java中的interface,而是有點像C++中的Concept,對泛型做類型檢查用的。

          泛型函數(shù)

          fn PrintSummary[T:! Summary](x: T) {
            Console.Print(x.Summarize());
          }

          定義了一個支持Summary泛型接口的泛型函數(shù)PrintSummary

          實現(xiàn)泛型接口

          class NewsArticle {
            ...
            impl as Summary {
              fn Summarize[meSelf]() -> String { ... }
            }
          }

          所以可以使用泛型函數(shù)來調(diào)用實現(xiàn)了泛型接口的類對象

            // n 是 NewsArticle類型
            PrintSummary(n);

          也可以直接調(diào)用

            // n 是 NewsArticle類型
            n.Summarize();

          擴展其他包的API

          import OtherPackage;

          interface Summary {
            fn Summarize[meSelf]() -> String;
          }

          // 泛型函數(shù)
          fn PrintSummary[T:! Summary](x: T) {
            Console.Print(x.Summarize());
          }

          // 擴展外部API的接口
          external impl OtherPackege.Tweet as Summary {
            fn Summarize[meSelf]() -> String { ... }
          }

          fn SummarizeTweet(t: Tweet) {
            PrintSummary(t);
          }

          我們導入了一個外部的包OtherPackege,它之中有一個Tweet類型,然后我們可以通過external impl來擴展它支持它本不存在的泛型接口。

          指針

          基本語法:

            // 定義i32類型變量x,值為5
            var x: i32 = 5;
            // 把x的值改成10
            x = 10;
            // 定義i32*類型的指針p,指向變量x的地址
            var p: i32* = &x;
            // 通過指針修改x的值為7
            *p = 7;
            // 定義i32*類型的指針q,使用&*p,同樣指向變量x的地址
            var q: i32* = &*p;
            // 通過指針q修改x的值為0
            *q = 0;
            // 定義一個i32類型的變量y,值為0
            var y: i32 = *p;

          另外Carbon的指針不支持空指針,如果想表示不存在,使用Optional。

          與C++互操作

          與C++互操作是Carbon宣傳的重點,也是最大難點。現(xiàn)在Carbon語言還不完善,這里舉一個Keynote中演示的例子。

          有一個C++的頭文件circle.h

          struct Circle {
            float r;
          }

          Carbon調(diào)用C++

          然后編寫一個Carbon代碼文件:geometry.carbon

          package Geometry api;
          import Math;

          import Cpp library "circle.h";

          fn PrintArea(circles: Slice(Cpp.Circle)) {
            var area: f32 = 0;
            for (c: Cpp.Circle in circles) {
              area += Math.Pi * c.r * c.r;
            }
            Print("Total area: {0}", area);
          }

          可以通過 import Cpp library "circle.h"; 這種語法來引用C++頭文件中聲明的類型。

          C++調(diào)用Carbon

          寫一個C++的源文件:

          #include <vector>
          #include "circle.h"

          #include "geometry.carbon.h"

          auto main(int argc, char* argv) -> int {
            std::vector<Circle> circles = {{1.0}, {2.0}};

            Geometry::PrintArea(circles);
            return 0;
          }

          最后提醒

          最后再次提醒,某些KeyNote中演示的Carbon語法僅僅是當前規(guī)劃中的設計,但還沒有被實現(xiàn)。當前已經(jīng)實現(xiàn),能夠通過編譯語法,參考Github倉庫中explorer/testdata目錄中的代碼。

          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  97色网站在线观看免费视频 | 中文字幕亚洲日韩 | 91成人久久久久久久 | 中国黄色在线视频 | 久久久久久久免费视频 |