天天看點

c++函數重載、預設參數、命名空間的解析

1.c和c++的優缺點解析

c語言屬于面向過程。

優點是:性能比面向對象高,因為類調用時需要執行個體化,開銷比較大,比較消耗資源。

缺點:沒有面向對象易維護、易複用、易擴充

c++屬于面向對象

優點是:易維護、易複用、易擴充,由于面向對象有封裝、繼承、多态性的特性,可以設計出低耦合的系統,使系統更加靈活、更加易于維護

缺點:性能比面向過程低

面向對象程式設計(英語:Object-oriented programming,縮寫:OOP)是一種程式設計範型,同時也是一種程式開發的方法。對象指的是類的執行個體。它将對象作為程式的基本單元,将程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充性

而c++是基于面向對象的語言,因為它包含了c的一部分,而c語言是面向過程。面向對象更符合人類思維模式。

2.函數重載解析

各位應該都知道在c語言中不支援重載,而c++中卻支援重載,這是為什麼呢?接下來我們仔細分析分析。

舉例建立三個檔案:test.h test.c main.c

執行檔案時分為下面四個過程

過程 執行的操作 生成的檔案
1.預處理 展開頭檔案、宏替換、去掉注釋、條件編譯 test.i main.i
2.編譯 檢查文法詞法并生成彙編代碼 test.s main.s
3.彙編 彙編代碼變為機器認識的機器碼 test.0 main.o
4.連結 連結到一起生成可執行程式 a.out
這是main.c中的函數
#include"test.h"

void func(int i)
{
    count<<i<<endl;
}

int main()
{
    func);
    func("c");

}
           
這是test.c的函數
#include"test.h"

void func(char c)
{
    count<<"hello world"<<endl;
}
           
這是test.h函數
#pragma once
#include<stdio.h>
#include<windows.h>
           

當你這時候編譯時就會出現這種錯誤: fatal error LNK1169: 找到一個或多個多重定義的符号

這就是重定義的錯誤,就算兩個函數參數不一樣,但依然還會重定義,因為在c語言連結時将main.o和test.o 合并時,在兩個檔案中查找func函數,當發現兩個檔案中都有func函數就會産生沖突,因為它是以名字查找的。

而c++是可以重載的

eg:

原函數 Linux下的反彙編定義的函數名字
void func(int i) _Z4funci
void func(char c) _Z4funcc
int max(int a,int b) _Z3maxii
double max(double a,double b) _Z3maxdd
看上面例子可得:c++ 中底層彙編語言中會将重載函數名映射為傳回類型+函數名+參數清單。這樣c++有同名函數時,連結時隻要參數類型或者順序不一樣就可以調用

3.預設參數解析

c++中的預設參數定義:在聲明函數的某個參數的時候為之指定一個預設值,在調用該 函數的時候如果使用預設值,你就沒必要指定該參數了。

void func2(int x, int y = );//聲明
void func1(int x = , int y = )//定義
{
    cout << x << ' ' << y << endl;

}
void func2(int x, int y)
{

    cout << x << ' ' << y << endl;

}
void func3(int x = , int y = )
{
    cout << x << ' ' << y << endl;

}
int main()
{

    func1();
    func2();
    func3(,);
    system("pause");
    return ;
}
           

就像func1在調用時實參為空,這就叫做預設參數,而在定義時有預設參數并且已經給出預設值,函數調用時就可以直接調用。而func2中隻省略了右邊參數y的值,是以實參隻寫了一個參數,func3中實參都寫了,是以調用時就不會用到預設參數的值,如果沒有寫就會直接調用預設參數

預設參數有一下規則:

1.調用時你隻能從最後一個參數開始進行省略,中間不能間斷。

2.預設值必須是常量

3.函數聲明時有預設參數,定義時就不能給出預設參數了,就像func2()一樣

4.預設參數與函數重載一塊使用時就要注意了

如果一組重載函數(可能帶有預設參數)都允許相同實參個數的調用,将會引起調用的二義性。例如:
void func(int x); //重載函數一
void func(int x,int y); //重載函數二,帶有預設參數
void func(int x,int y); //重載函數三,帶有預設參數
func); //error: 到底調用3個重載函數中的哪個?
func) //error:到底調用後面2個重載函數的哪個?
           

這樣就會出現問題,是以讀者在應用時要特别注意

5.預設值的限定:預設值可以是全局變量、全局常量,甚至是一個函數,但不能是局部變量,局部變量

因為預設參數的函數調用是在編譯時确定的,而局部變量的位置與值在編譯時均無法确定

4.命名空間解析

命名空間:在C++ 中,名稱(name)可以是符号常量、變量、宏、函數、結構、枚舉、類和對象等等。為了避免在大規模程式的設計中,以及在程式員使用各種各樣的C++庫時,這些辨別符的命名發生沖突,标準C++引入了關鍵字namespace(命名空間),這些辨別符的作用域隻在本空間域内有效,進而合理的解決命名沖突。

eg:

namespace n1
{
    int a = ;
    namespace n2
    {
        int a = ;
    }
}

cout << n1::a << endl;
cout << n1::n2::a << endl;
           

上面例子說明在不同的命名空間裡可以定義相同的名稱,不會出現命名沖突問題

c++中有一個标準的命名空間

using namespace std;

C++ 庫的所有辨別符都是在std的命名空間中定義的,或者說标準頭檔案(iostream)中的函數、類、對象和類模闆是在命名空間std中定義的。是以在C++程式的一開始,就用using namespace對std進行全局聲明

如果你一開始不寫這個命名空間就會編譯出錯,要麼你就得給是以std命名空間下的成員加上這個eg:

std::cout << n1::a << std::endl;
    std::cout << n1::n2::a << std::endl;
           

繼續閱讀