重載與命名空間(學習筆記)

時間:2014.07.01

地點:基地

-----------------------------------------------------------------------------------------

命名空間對函數匹配的影響主要表現在:使用using聲明或using指示能將某些函數添加到候選函數集(不同版本)中

一、與實參相關的查找與重載

  對於接受類類型實參的函數而言,其名字查找是在實參的類所在的命名空間中進行。我們將在實參類以及實參類的基類所屬的命名空間中搜尋候選函數。這些命名空間中所有與被調函數同名的函數都將被添加到候選集中,即使其中某些函數在調用語句處不可見。比如:

namespace NS
{
   class Quote{/*......*/};
   void Display(const Quote&){/*......*/}
}
在命名空間NS下,我們定義了一個Quote類和Display函數,該函數接受Quote類類型的參數。

class BulkItem:public NS::Quote
{
  /*......*/
};
類BulkItem繼承命名空間NS下的類Quote
int main()
{
  BulkItem book1;
  Display(book1);
  return 0;
}
在這裏,我們傳遞給Display的實參是一個類類型BulkItem,於是調用語句的候選函數查找不僅會在調用語句所在的作用域即main()函數中查找,它還會在BulkItem已經其基類Quote所屬的命名空間中查找。即在這裏表現爲命名空間NS中聲明的函數Display(const Quote&)也將被添加到候選函數集當中。從而在這裏可以正確地調用到Display函數。

-----------------------------------------------------------------------------------------

二、重載與using聲明

  using聲明語句聲明的只是一個名字,而不是一個特定的函數。比如:
using NS::print(int);  //這樣會編譯錯誤,因爲using不能聲明特定函數
using NS::print;       //正確,using在這裏只聲明一個名字
這樣之後,該函數的所有版本都將被引入到當前作用域之中
  using聲明語句引入的函數將重載該聲明語句所屬作用域中已有的其他同名函數(即只要條件符合,using聲明語句引入的函數與該聲明語句所在作用域中的其它同名函數會構成重載關係)。比如當using語句聲明出現在局部作用域中時,則引入的名字將隱藏外層作用域的相關聲明,與本作用域中的同名函數重載。但另一方面,如果using聲明所在的作用域中已經有一個函數與新引入的函數同名且形參列表相同,則該using聲明將引發錯誤
-----------------------------------------------------------------------------------------

三、重載與using指示

  using指示可將命名空間的成員提升到外層作用域中,如果命名空間的某個函數與該命名空間所屬作用域的函數同名,則命名空間中函數將被添加到重載集合中。比如:
namespace  my_space
{
  extern void print(int);
  extern void print(double);
}
//接下來是一個普通的函數聲明
void print(const  std::string&);
//using指示,它將把該命名空間名字提升到外層作用域,並與外層作用域同名不同參的函數重載,比如在這裏using指示把名字添加到print調用的候選函數集中
using namespace myspace;
//於是現在掉用print函數時有如下候選函數版本
//myspace中的print(int)
//myspace中的print(double)
//當前域中顯式聲明的print(const std::string&)
void FooBar(int ival)
{
  print("Value: ");  //該句會調用全局函數的print(const string&)
  print(ival);  //調用命名空間中的print(int)
}
注意using聲明與using指示的區別:
using聲明僅僅是聲明命名空間中存在的名字,把該命名空間中的所有該名字的函數版本或該名字變量引入到當前作用域中。而using指示時把命名空間中的所有成員都提升到外層作用域之中。而且,對於using指示而言,引入一個與已有函數函數名和形參列表全部都相同的函數時也並不會產生錯誤。此時,只需要指明要調用的版本是命名空間中的版本還是當前作用域的版本即可。
-----------------------------------------------------------------------------------------

四、多using指示與重載

若是存在多個using指示,則來自每個命名空間的名字都會成爲候選函數集的一部分。比如:
namespace SpaceOne
{
  int print(int);
}
namespace SpaceTwo
{
  double print(double);
}
//使用using指示從不同的命名空間中創建一個重載函數集合
using namespace SpaceOne;
using namespace SpaceTwo;
//還在當前域中定義一個同名不同參函數
long double print(long double);
int main()
{
  print(1);     //調用SpaceOne中的print(int)
print(2.1);  //調用SpaceTwo中的print(double)
return 0;
}
在上面,全局作用域中,函數print的重載集合中包括print(int),print(double)和print(long double),儘管它們的聲明位於不同作用域中,但他們都屬於mian函數中print調用的候選函數集。




發佈了193 篇原創文章 · 獲贊 53 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章