• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 情有獨鐘C++:Visual C++ .NET編譯器的新特性

    發表于:2007-07-01來源:作者:點擊數: 標簽:
    廣州市天河村迎福七巷9號 王凌峰 本文假定您已熟悉 C++ 。 摘要 老資格的 C++ 程序員 們都想知道:他們賴以生存的 C++ 語言在 C# 和微軟的 .NET 的沖擊下何去何從?本文將對 .NET 世界中的 C++ 進行簡要描述。在 .NET 中,C++ 分裂為兩大陣營:受管代碼 (Man

    廣州市天河村迎福七巷9號 王凌峰

    本文假定您已熟悉 C++ 。
    摘要
    老資格的 C++ 程序員們都想知道:他們賴以生存的 C++ 語言在 C# 和微軟的 .NET 的沖擊下何去何從?本文將對 .NET 世界中的 C++ 進行簡要描述。在 .NET 中,C++ 分裂為兩大陣營:受管代碼 (Managed Code) 和非受管代碼 (Unmanaged Code)。非受管代碼不使用通用語言運行時環境 (CLR) ,而受管代碼則用到了 Managed Extensions for C++ 。本文將對兩者分別討論。
    C++ 社區給人的感覺就象一個大家庭:初生的小寶寶總是倍受呵護,而年長的孩子卻是無人關心。如此被忽視,又怎能教人不心痛?事實上,技術領域的情況比這更糟:技術的革新實在太快,人們疲于奔命卻無可奈何,否則連飯碗都保不住了。
    如今,微軟公司的新產品 .NET 框架被炒得沸沸揚揚——的確很不錯;眾人還對所謂的 C# 語言連聲喝彩。作為 C++ 的程序員,心里卻很不是滋味:我是不是也要改行學 C# 了?因為人們只有在比較 C# 與 C++ 才會偶爾提及 C++ 了。
    C++ 程序員要過時了嗎?絕不!本文先簡要描述 Visual Studio .NET 為 C++ 引入的新特性,然后再介紹微軟公司對新版 C++ 的計劃。首先從兩個方面來談談 Visual Studio .NET 里的 C++ :標準的 C++ 和 Managed Extensions for C++ 。
    對標準 C++ 的擴充主要是為了保持兼容性;也就是說,為了保持國際標準化組織 (ISO) 所規定的 C++ 語言特性。而 Managed Extensions for C++ 則是為了把 C++ 納入 .NET 框架之中。
    Visual Studio .NET 下的標準 C++
    為了保持對 ISO 標準的兼容性,標準 C++ 作了如下改進:
    (1) 虛擬函數的返回值現在支持共變 (covariant) 類型了,這是類層次體系上的一個重大改進;
    (2) 支持對靜態整數類型常量( static const integer )成員的顯式初始化;
    (3) 主函數的返回值默認為 0 。
    現在我來逐一介紹它們。
    第一項是增加 covariant 返回類型,它已經由標準委員會核準。也就是說,如果基類的某個虛擬函數返回值是該類本身的實例,那么它在派生類中被重載后也能返回此派生類本身的實例。在類層次體系中,這是一種很重要的設計模式;在 Visual Studio .NET 中,它也大受歡迎。
    例如,對于抽象基類 Query :
    class Query {
    public:
    virtual Query *clone() = 0;
    // ...
    };
    如果想要其派生類實例 NotQuery 的 clone 函數返回一個 NotQuery 對象,即:
    class NotQuery {
    public:
    virtual Query *clone()
    { return new NotQuery( this ); }
    // ...
    public:
    Query *operand;
    };
    當沒有 covariant 返回類型支持時,clone 的返回類型必然是 Query* :
    // without covariant return type support
    virtual Query* clone()
    { return new NotQuery(
    this ); }
    此時如果把 clone 的返回值分配給 Query* 類型的指針,那么一切工作正常:
    NotQuery::NotQuery( const NotQuery &rhs )
    { operand = rhs.operand->clone(); }
    但是如果要分配給 NotQuery* 類型的指針呢?
    NotQuery nq( new NameQuery( "Shakespeare" );
    這樣就不行了:
    // oops: illegal assignment ...
    NotQuery *pnq0 = nq->clone();
    只能這樣:
    // ok: required explicit cast ...
    NotQuery *pnq1 =
    static_cast<NotQuery*>(nq->clone());
    現在有了 covariant 返回類型,你就可以顯式返回 NotQuery* 類型了:
    // with covariant return type support
    virtual NotQuery* clone()
    { return new NotQuery( this ); }
    于是,clone 的返回類型變得更直觀,不再需要強制類型轉換了:
    這樣是對的:
    // ok: implicit conversion ... ;
    Query *pq = nq->clone();
    這樣也沒問題:
    // ok: no conversion necessary ... ;
    NotQuery *pnq = nq->clone();
    第二項是靜態整數常量類型成員的顯式初始化,它對 C++ 的影響就沒有 covariant 返回類型那么大了。它僅僅給使用常量表達式(如:定長數組)的類的設計帶來了方便。例如:
    class Buffer {
    static const int ms_buf_size = 1024;
    char m_buffer[ ms_buf_size ];
    };
    static const int 類型成員被初始化以后,就可以為本類的其它成員所用,例如設置 m_buffer 的大小,而不用象以前那樣,使用枚舉變量了。
    第三項是主函數的默認返回值為 0 。主函數的返回值代表程序的退出狀態。習慣上,返回 0 代表程序正常結束。在標準 C++ 里,如果沒有顯性指定返回值,編譯器就會自動地在主函數末尾插入一行:
    return 0;
    進入 Visual Studio .NET 時代,Visual C++ 終于支持它了!
    Visual Studio .NET 下的受管 C++
    Visual Studio .NET 的 Managed Extensions for C++ 提供了三種基本的應用策略:
    (1) 為原有的 API 提供 .NET“包裝”,把 C++ 類統統移植到 .NET 平臺中。
    (2) 混用 C++ 類與微軟 .NET 的三種框架類:
    核心語言支持,例如:收集類和系統輸入/輸出;
    基礎程序類, 例如:線程支持,網絡套接字和正規表達式;
    應用領域支持,例如:XML、ASP.NET、Web 服務、Windows 窗體、ADO.NET,等等。
    (3) 象 C# 和 Visual Basic 那樣直接操作 .NET 環境。然而,目前尚無相應的快速開發工具(RAD)用于 Windows 窗體和 Web 表單的可視化編程。
    先來看看第一種方案:用 .NET 包裝原有的代碼。在我的 C++ Primer 一書 (Addison-Wesley,1998) 中,我示范了一個相當大的文本查詢系統,其中大量使用了 STL 容器類用于解析文本文件和建立數據結構。它的引用文件內容如下:
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <utility>
    #include <map>
    #include <set>
    #include <iostream>
    #include <fstream>
    #include <stddef.h>
    #include <ctype.h>
    using namespace std;
    創建的數據結構如下:
    typedef pair<short,short> location;
    typedef vector<location> loc;
    typedef vector<string> text;
    typedef pair<text*,loc*> text_loc;
    class TextQuery {
    public:
    // ...
    private:
    vector<string> *lines_of_text;
    text_loc *text_locations;
    map<string,loc*> *word_map;
    Query *query;
    static string filt_elems;
    vector<int> line_cnt;
    };
    Query 類是用于解釋查詢語言的抽象基類,下面演示了它的功能:
    Enter a query-please separate each item by a space.
    Terminate query (or session) with a dot( . ).
    ==> fiery && ( bird || shyly )
    fiery ( 1 ) lines match
    bird ( 1 ) lines match
    shyly ( 1 ) lines match
    ( bird || shyly ) ( 2 ) lines match
    fiery && ( bird || shyly ) ( 1 ) lines match
    Requested query: fiery && ( bird || shyly )
    (3) like a fiery bird in flight. A beautiful fiery bird, he tells her,
    主程序代碼如下:
    int main()
    {
    TextQuery tq;
    tq.build_up_text();
    tq.query_text();
    }
    現在我把 TextQuery 接口提交給 .NET 平臺,沒有修改代碼,更沒有重寫函數。最終,一切順利。假如移植到 .NET 平臺必須完全重寫代碼的話,我可能就不會那么做了。幸好受管 C++ 提供了包裝移植的方式。下面是包裝的一種方式:
    #include "TextQuery.h"
    __gc class TextQueryNet
    {
    private:
    TextQuery *pquery;
    public:
    TextQueryNet() : pquery( new TextQuery()){}
    ~TextQueryNet(){ delete pquery; }
    void query_text() { pquery->query_text(); }
    void build_up_text() { pquery->build_up_text();}
    // ...
    };
    關鍵字 __gc 用于指定受管類,它們接受垃圾回收器管理,占用通用語言運行時 (CLR) 受管堆。與原先的代碼一樣,我把原生類 (native class) 宣告為指針類型成員,使用關鍵字 new 在非受管堆分配空間,由于它不支持垃圾回收管理,故在析構函數中使用 delete 回收空間。build_up_text 和 query_text 都是殘余 (stub) 函數,用于呼叫真正的 TextQuery 對象。
    作為對照,我們來看看由 Managed C++ Project Wizard 自動生成的主函數:
    #include "stdafx.h"
    #using <mscorlib.dll>
    #include <tchar.h>
    using namespace System;
    #include "gc_TextQuery.h"
    int _tmain(void)
    {
    Console::WriteLine(
    S"Beginning managed wrapper test ..." );
    TextQueryNet *tqn = new TextQueryNet();
    tqn->build_up_text();
    tqn->query_text();
    Console::WriteLine(
    S"Ending managed wrapper test ..." );
    return 0;
    }
    現在,我們來討論 .NET 框架的利用。如果有人問我,ISO 標準 C++ 最大的缺點是什么?我的答案是:它沒有提供支持諸如線程、網絡編程、正規表達式以及XML 等應用領域的標準庫。標準委員會已將其列入下一輪工作計劃,但那是一年以后的事了。目前我們怎么辦?其實,.NET 框架已經提供了引人入勝的解決方案。下面演示一個簡單的 Socket 服務器類,它利用了 .NET 框架:
    // include the necessary assemblies
    #using <mscorlib.dll>
    #using <System.dll>
    #using <System.Data.dll>
    #using <System.Xml.dll>
    // open up the associated namespaces
    using namespace System;
    using namespace System::Threading;
    using namespace System::Data;
    using namespace System::Data::SqlClient;
    using namespace System::Collections;
    using namespace System::Net::Sockets;
    // ok: here is our class
    __gc class SocketDemo_Server
    {
    private:
    static const int port = 4554;
    static const int maxPacket = 128;
    TcpListener *tcpl;
    DataSet *ds;
    DataRowCollection *rows;
    public:
    SocketDemo_Server();
    void Start();
    void handleConnection();
    // grab the data from the SQL database
    void retrieveData();
    };
    它的功能是查詢 Northwind 公司職員的電話號碼;其中的 SQL 數據庫可以在 Visual Studio .NET 發行版本中找到。
    再來看看它在運行過程中對三位客戶的處理記錄:
    Server[4554]: OK: started TcpListener ...
    Server[4554]: OK: listening for connections ...
    Server[4554]: OK: retrieved SQL database info ...
    Server[4554]: OK: a client connected ...
    Server[4554]: OK: client requested phone # for Fuller
    Server[4554]: OK: first request for Fuller
    Server[4554]: Phone number for Fuller: (206) 555-9482
    Server[4554]: OK: a client connected ...
    Server[4554]: OK: client requested phone # for King
    Server[4554]: OK: first request for King
    Server[4554]: Phone number for King: (71) 555-5598
    Server[4554]: OK: a client connected ...
    Server[4554]: OK: client requested phone # for Fuller
    Server[4554]: OK: cached request for Fuller
    Server[4554]: Phone number for Fuller: (206) 555-9482
    Server[4554]: OK: a client connected ...
    Server[4554]: OK: client requested phone # for Musil
    Server[4554]: OK: first request for Musil
    Server[4554]: Phone number for Musil: Sorry. Cannot be found.
    下面是 Start 函數的實現代碼:
    void SocketDemo_Server::
    Start()
    {
    try
    {
    tcpl = new TcpListener( port );
    tcpl->Start();
    Console::WriteLine(
    S"Server[{0}]: OK: started TcpListener ... ",
    __box( port ));
    // retrieve the data from the data base ...
    Thread *tdata =
    new Thread( new ThreadStart( this,
    &SocketDemo_Server::retrieveData ));
    tdata->Start(); // ok: kick off the thread ...
    // thread to handle a socket connection ...
    Thread *tconnect =
    new Thread( new ThreadStart( this,
    &SocketDemo_Server::handleConnection ));
    tconnect->Start();
    }
    catch( Exception *ex )
    {
    Console::WriteLine(
    S"Oops: Unable to Set Up SocketDemo_Server" );
    Console::WriteLine( ex->ToString() );
    }
    }
    我們看到,Start 函數利用 Thread 類生成許多線程,分別響應每位客戶的請求。此外,由于 WriteLine 函數需要引用參數,故我們使用了 __box( port ) 。
    再有,Exception 類是一切 .NET 的異常處理類的基類;ToString 方法用于顯示整個堆棧 (酷極了); ThreadStart 是 代表 (delegate) 類型 —— 既能指向靜態成員函數,也能指向動態成員函數的通用指針類型。
    當然,它的實現代碼還可以進一步完善,但是我想您現在已經體會到 .NET 框架的強大和易用性了。更重要的是,您已經看到,在 C++ 里面使用它是多么的簡單!
    C++ 的未來
    本文是對 Visual Studio .NET 下的 C++ 的簡單介紹,希望在讀過之后,您會對 Visual C++ 充滿信心,因為它不僅僅是 Visual Studio .NET 中的一份子,而且是其重要的一員。為了體現其重要性,微軟公司 Visual C++ 工作組正在努力工作以爭取盡早完成新一代 Visual C++ 的過渡版本,它將具有本文所述的全部新特性。在 ISO 標準 C++ 的兼容性方面,工作組已經邁出了一大步。對于優秀的程序員來說,它意味著模板,模板,還是模板!諸如 Loki 和 Boost 等大量使用模板的第三方程序庫,正在緊張工作中。正如人們在電影中說的那樣:“瞧著吧,好戲還在后頭呢!”


    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>