<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 134,comments - 22,trackbacks - 0

    ADL(Koenig) 查找

    ADL ,參數相關查找,也稱作為 Koenig 查找(以 Andrew Koenig 的名字命名),是指在編譯器對無限定域的函數調用進行名字查找時,所應用的一種查找規則。

    首先來看一個函數所在的域的分類:

    1 :類域(函數作為某個類的成員函數(靜態或非靜態))

    2 :名字空間域

    3 :全局域

    而 Koenig 查找,它的規則就是當編譯器對無限定域的函數調用進行名字查找時,除了當前名字空間域以外,也會把函數參數類型所處的名字空間 加入查找的范圍。

    ADL 就是為了確保使用類型 X 的對象 x 時能夠像使用 X 的成員函數一樣簡單 (ensure that code that uses an object x of type X can use its nonmember function interface as easily as it can use member functions) 。

    根據 ADL 規則,如果非成員函數想和類型一起被使用,應該將它們置于同一個名字空間中。換句話說,和類型 X 放在同一名字空間下的非成員函數,也是 X 接口的一部分。 ( 常見的有 <<or>> 操作符 )

    示例:

    #include <iostream>

    //class N     // 類域

    //{

    //public :

    //     enum E {e1};

    //     void f(E)

    //     {

    //            std::cout << "N::f(N::E) called\n";

    //     }

    //};

    namespace N{   // 名字空間域

           enum E {e1};

           void f(E){

                  std::cout << "N::f(N::E) called\n";

           }

    }

    void f(int)

    {

           std::cout << " ::f(int) called\n";

    }

     

    int main()

    {

           ::f(N::e1);     // 受限函數,禁用 ADL  // 輸出 ::f(int) called

           f(N::e1);      // 普通查找到 f();

           return 0;

    }

     

    上述例子,如果 N 為 class ,輸出為: ::f(int) called ;如果 N 為名字空間,輸出: N::f(N::E) called 。

    也就是說 ADL 僅會將參數所在的名字空間中的函數名字加入查找范圍。

    調用函數時,顯式地限定名字空間將禁用 ADL 查找 ,加快解析過程。

     

    Argument Dependent Lookup (ADL)解析

    ADL,參數相關查找,也稱作為Koenig查找(以Andrew Koenig的名字命名,有興趣可以看Scott Meyer的文章The Most Important C++ People...Ever),是指在編譯器對無限定域的函數調用進行名字查找時,所應用的一種查找規則。

    f(x, y, z); // unqualified
    N::f(x, y, z); // qualified

    上面的函數調用,第一個f就是無限定域的函數調用,第二個則限定了在名字空間N里面,也是說使用了完全限定名。
    我們首先來看一個函數所在的域的分類:
    1:類域(函數作為某個類的成員函數(靜態或非靜態))
    2:名字空間域
    3:全局域
    而Koenig查找,它的規則就是當編譯器對無限定域的函數調用進行名字查找時,除了當前名字空間域以外,也會把函數參數類型所處的名字空間加入查找的范圍。
    Herb提供的解釋(Exceptional C++, Item 31)

    Koenig Lookup(simplified): If you supply a function argument of class type (here x, of type A::X), then to look up the correct function name the compiler considers matching names in the namespace (here A) containing the argument's type.

    請看下面的例程:
    #include <iostream>
    usingnamespace std;

    namespace Koenig
    {
        class KoenigArg
        
    {
        public:
              ostream
    & print(ostream&out) const
             
    {
                     out<<member_<<endl;
              }


              KoenigArg(
    int member =5) : member_(member){}

        
    private:
             
    int member_;
         }
    ;


         inline ostream
    &operator<<(ostream&out, const KoenigArg& kArg)
        
    {
             return kArg.print(out);
         }

    }


    int main()
    {
         Koenig::KoenigArg karg(10);
         cout
    <<karg;

        
    char c;cin>>c;

        
    return0;
    }

    我們通常都會寫如上的代碼,使用operator<<打印對象的狀態,但是ostream& operator<<(ostream& out, const KoenigArg& kArg) 的定義是處于名字空間Koenig,為什么編譯器在解析main函數(全局域)里面的operator<<調用時,它能夠正確定位到Koenig名字空間里面的operator<<?這是因為根據Koenig查找規則,編譯器需要把參數類型KoenigArg所在的名字空間Koenig也加入對operator<<調用的名字查找范圍中。

    如果沒有Koenig查找規則,我們就無法直接寫cout<<karg;,而是需要寫類似Koenig::operator<<(std::cout, karg); 這樣的代碼(使用完全限定名)。嗯,即不直觀也不方便是嗎?更重要的是如果我們寫的是模版代碼,在模版參數還沒有實例化之前,我們根本就不知道參數所處的名字空間,比如:

    template<typename T>void print(const T& value)
    {
         std::cout<<value;
    }


    print(karg);
    很顯然,你的模版代碼根本無法確認T是來自那個名字空間,直到編譯器對模版實例化(print(karg); 被調用)。
    對Koenig查找規則的一個異議是,由于Koenig查找規則的存在,處于某個名字空間的函數調用的重載決議會受到另外一個名字空間的自由函數所影響,僅僅是由于它使用了另外一個名字空間的類型作為參數。在這樣的規則下,名字空間看起來不像我們一般所想象的那樣是完全封閉和獨立的。
    我們應該怎么解釋這樣的異議呢?這樣隱諱的影響或者依賴性是合理的嗎?Herb認為,如果我們把另外一個名字空間的自由函數(非類成員函數)也看作是它所涉及的類型的接口的一部分,很顯然,它應該參與這樣的重載決議,這樣的跨越名字空間的影響是合理的。從而導出了Herb在傳統類定義之上的一個更詳細和完整的解釋(請參考Exceptional C++, Item 32)。
    傳統的類定義:

    A class describes a set of data, along with the functions that operate on that data.

    一個類描述了數據的集合以及操作這些數據的函數。
    Herb的類定義,稱之為接口準則(Interface Principle):
    For a class X, all functions, including free functions, that both
    "Mention" X
    Are "supplied with" X

    are logically part of X, because they form part of the interface of X.

    對應類X來說,所有函數,包括自由函數,只要它們
             提及X(跟X有關)
             X一起提供
    都在邏輯上被認為是X的一部分,因為它們是X的接口的一部分。
    關于Koenig查找,我們該說的都說了嗎?其實未然,之前所描述的只是Koenig查找一般可能發生的狀況,當Koenig查找規則和C++ 原來的Ordinal Lookup(OL,順序查找規則)混合在一起的時候,它們之間的組合所產生的狀況要比之前的例子復雜的多……
    posted on 2009-12-13 11:37 何克勤 閱讀(385) 評論(0)  編輯  收藏 所屬分類: C/C++
    主站蜘蛛池模板: 亚洲一区影音先锋色资源| 亚洲国产美女精品久久久久∴| 久热综合在线亚洲精品| 老司机午夜精品视频在线观看免费 | 中文字幕亚洲精品资源网| 久青草视频在线观看免费| 日本免费中文字幕| 久久久亚洲欧洲日产国码农村| a毛片免费在线观看| 午夜亚洲www湿好大| 精品免费久久久久久久| 亚洲永久在线观看| 日本一道在线日本一道高清不卡免费 | 国产猛烈高潮尖叫视频免费 | 中国极品美軳免费观看| 九月丁香婷婷亚洲综合色| 久久一本岛在免费线观看2020| 久久亚洲精品中文字幕| 色窝窝免费一区二区三区| 亚洲国产精品精华液| 在线免费中文字幕| 亚洲AV无码久久久久网站蜜桃 | 少妇高潮太爽了在线观看免费| 亚洲日本在线电影| 亚洲精品国产电影| 精品国产免费一区二区三区香蕉| 久久青青成人亚洲精品| 国产v精品成人免费视频400条| 亚洲色偷偷综合亚洲av78| 人妻无码一区二区三区免费| 亚洲一级毛片视频| 亚洲AV无码乱码在线观看牲色| 国产一级婬片A视频免费观看| 麻豆亚洲av熟女国产一区二| 欧洲美熟女乱又伦免费视频| 精品国产免费一区二区三区| 亚洲经典在线中文字幕| 免费A级毛片无码A| 久久免费看黄a级毛片| 免费激情网站国产高清第一页| 亚洲国产精品VA在线观看麻豆 |