C++:名稱空間,函式過載與預設引數
本篇部落格主要針對與c與c++不同的地方做以總結。
C++:在C的基礎上添加了一些新的特性
C++的學習主要分為以下幾個大的板塊。
- c
- 類 & 物件
- 繼承 & 多型
- 模板 & 泛型程式設計
- 異常處理
- C++庫 & STL
也就是說,之前我們所學過的c語言的所有知識在c++中仍然適用。
資料型別
- 內建型別
- 自定義型別:struct/class/enum/union
名稱空間
名稱空間域是隨c++標準引入的,相當於一個更加靈活的檔案域,可以用花括號把檔案的一部分括起來,並以關鍵字namespace開頭給它起一個名字。
namespace name1
{
int a=10;
}
int main()
{
std::cout<<a<<std::endl;
}
//這段程式碼是編不過去的,原因是:
//a變數並沒有指定是哪個名稱空間的變數。所以編譯器找不到這個變數。
再來看下面這個例子:
namespace name1
{
int a=10;
}
namespace name2
{
int a=20;
}
int main()
{
int a=30;
std::cout<<a<<std::endl;
std::cout <<name1::a<<std::endl;
std::cout<<name2::a<<std::endl;
}
//結果:
//30
//10
//20
可以看到,我們在main函式中定義了一個區域性變數a,輸出時不指定名稱空間就會輸出該變數a,這是源於c語言中的就近原則,編譯器向上找到了一個最近的區域性變數a,就不會去別的地方找,直接輸出。
第二個輸出10,原因是指定了名稱空間name1,所以編譯器會在該名稱空間內找該變數a,name2同理。
也就是說,名稱空間的意義實際上是為了防止命名衝突的。
那麼我們經常寫c++程式碼時,會寫一句:
using namespace std;
這是為什麼?
原因是由於:標準c++庫中的所有元件都是在一個被稱為std的名字空間中宣告和定義的。因此,只要使用c++庫中的元件,只要寫一個using namespace std即可。或者使用std::成員的方式來使用。這句話的實際意思是,將std的名稱空間展開到全域性域上,所以在你的程式碼任何地方都可以使用該名稱空間中的元件,但是,尤為重要的一點,一旦你將該名稱空間展開為全域性域之後,變數的命名就不能夠與std中的識別符號重名。
如下面的程式碼:
using namespace std;
int main()
{
int max=10;
std::cout<<max(1,2)<<std::endl;
}
//顯然這兩個max的含義不同,第一個max是我自己定義的變數,第二個max是std庫裡的函式名。
輸入輸出
cout是標準輸出流物件,<< 是輸出操作符
cin是標準輸入流物件,>>是輸入操作符
都屬於C++標準庫,所以都在std的名字空間裡面。
格式控制輸出流,不如使用c語言輸出更加直觀
例項:
cout<<"hello world!"<<endl;
cin>>num;
預設引數
全預設引數
int add(int a=0,int b=0)
{
return a+b;
}
半預設引數:只能預設右邊的值
int add(int a,int b=0)
{
return a+b;
}
注意:預設只能從右向左預設。
*函式過載**
在同一作用域類,一組函式的函式名相同,引數列表不同
“不同” 可以是:引數個數不同/引數型別不同/返回值可同可不同
例項:以下函式均構成函式過載。
int Add(int a)
{
return a+10;
}
int Add(int a,int b)
{
return a+b;
}
int Add(char ch1,char ch2)
{
return ch1+ch2;
}
int Add(int a,char ch2)
{
return a+ch2;
}
int Add(char ch1,int b)
{
return ch1+b;
}
c++是如何支援過載的?
這是由於c++函式名稱修飾規則。我在Linux下使用objdump工具可以檢視到函式名稱修飾的區別。
可以看到c++在函式名稱修飾上會在該名稱前加上字首與字尾,但是,字尾很明顯加入了該函式每個引數型別的首字母。