重載和重寫的區別


1.重寫(Override)

從字面上看,重寫就是 重新寫一遍的意思。其實就是在子類中把父類本身有的方法重新寫一遍。子類繼承了父類原有的方法,但有時子類並不想原封不動的繼承父類中的某個方法,所以在方法名,參數列表,返回類型(除過子類中方法的返回值是父類中方法返回值的子類時)都相同的情況下, 對方法體進行修改或重寫,這就是重寫。但要注意子類函數的訪問修飾權限不能少於父類的。

總結:
1.發生在父類與子類之間
2.方法名,參數列表,返回類型(除過子類中方法的返回類型是父類中返回類型的子類)必須相同
3.訪問修飾符的限制一定要大於被重寫方法的訪問修飾符(public>protected>default>private)
4.重寫方法一定不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的檢查型異常

 

2.重載(Overload)

在一個類中,同名的方法如果有不同的參數列表(參數類型不同、參數個數不同甚至是參數順序不同)則視為重載。同時,重載對返回類型沒有要求,可以相同也可以不同,但不能通過返回類型是否相同來判斷重載。

總結:
1.重載Overload是一個類中多態性的一種表現
2.重載要求同名方法的參數列表不同(參數類型,參數個數甚至是參數順序)
3.重載的時候,返回值類型可以相同也可以不相同。無法以返回型別作為重載函數的區分標准

方法的重載和重寫都是實現多態的方式,區別在於前者實現的是編譯時的多態性,而后者實現的是運行時的多態性。重載發生在一個類中,同名的方法如果有不同的參數列表(參數類型不同、參數個數不同或者二者都不同)則視為重載;重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的參數列表,有兼容的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對返回類型沒有特殊的要求,不能根據返回類型進行區分。

二、規則上的不同:

1、重載的規則:

①必須具有不同的參數列表。

②可以有不同的訪問修飾符。

③可以拋出不同的異常。

2、重寫方法的規則:

①參數列表必須完全與被重寫的方法相同,否則不能稱其為重寫而是重載。

②返回的類型必須一直與被重寫的方法的返回類型相同,否則不能稱其為重寫而是重載。

③訪問修飾符的限制一定要大於被重寫方法的訪問修飾符。

④重寫方法一定不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的檢查型異常。

三、類的關系上的區別:

重寫是子類和父類之間的關系,是垂直關系;重載是同一個類中方法之間的關系,是水平關系。

 

C++ bind和function用法

 

function是一個template,定義於頭文件functional中。通過function<int(int, int)> 聲明一個function類型,它是“接受兩個int參數、返回一個int類型”的可調用對象,這里可調用對象可以理解為函數指針(指針指向一個函數,該函數有兩個int類型參數,返回int類型,即:int (*p)(int, int)  )。

可調用對象:對於一個對象或表達式,如果可以對其使用調用運算符,則稱該對象或表達式為可調用對象。

C++語言中有幾種可調用對象:函數、函數指針、lambda表達式、bind創建的對象以及重載了函數調用運算符的類。

和其他對象一樣,可調用對象也有類型。例如,每個lambda有它自己唯一的(未命名)類類型;函數及函數指針的類型則由其返回值類型和實參類型決定。

function的用法:

1. 保存普通函數

void printA(int a)
{
     cout << a << endl;          
}

std::function<void(int a)> func;
func = printA;
func(2);   //2

2. 保存lambda表達式

std::function<void()> func_1 = [](){cout << "hello world" << endl;};    
func_1();  //hello world

3. 保存成員函數

class Foo{
    Foo(int num) : num_(num){}
    void print_add(int i) const {cout << num_ + i << endl;}
    int num_;  
};

//保存成員函數
std::function<void(const Foo&,int)> f_add_display = &Foo::print_add;
Foo foo(2);
f_add_display(foo,1);

在實際使用中,可使用auto關鍵字。


 

關於bind的用法:

可將bind函數看作是一個通用的函數適配器,它接受一個可調用對象,生成一個新的可調用對象來“適應”原對象的參數列表。

調用bind的一般形式:auto newCallable = bind(callable,arg_list);

其中,newCallable本身是一個可調用對象,arg_list是一個逗號分隔的參數列表,對應給定的callable的參數。即,當我們調用newCallable時,newCallable會調用callable,並傳給它arg_list中的參數。

arg_list中的參數可能包含形如_n的名字,其中n是一個整數,這些參數是“占位符”,表示newCallable的參數,它們占據了傳遞給newCallable的參數的“位置”。數值n表示生成的可調用對象中參數的位置:_1為newCallable的第一個參數,_2為第二個參數,以此類推。 from 《C++ primer》第五版

看代碼:

#include <iostream>
#include <functional>
using namespace std;
class A
{
public:
    void fun_3(int k,int m)
    {
        cout<<"print: k="<<k<<",m="<<m<<endl;
    }
};

void fun_1(int x,int y,int z)
{
    cout<<"print: x=" <<x<<",y="<< y << ",z=" <<z<<endl;
}

void fun_2(int &a,int &b)
{
    a++;
    b++;
    cout<<"print: a=" <<a<<",b="<<b<<endl;
}

int main(int argc, char * argv[])
{
    //f1的類型為 function<void(int, int, int)>
    auto f1 = std::bind(fun_1,1,2,3); //表示綁定函數 fun 的第一,二,三個參數值為: 1 2 3
    f1(); //print: x=1,y=2,z=3

    auto f2 = std::bind(fun_1, placeholders::_1,placeholders::_2,3);
    //表示綁定函數 fun 的第三個參數為 3,而fun 的第一,二個參數分別由調用 f2 的第一,二個參數指定
    f2(1,2);//print: x=1,y=2,z=3
 
    auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3);
    //表示綁定函數 fun 的第三個參數為 3,而fun 的第一,二個參數分別由調用 f3 的第二,一個參數指定
    //注意: f2  和  f3 的區別。
    f3(1,2);//print: x=2,y=1,z=3

    int m = 2;
    int n = 3;
    auto f4 = std::bind(fun_2, placeholders::_1, n); //表示綁定fun_2的第一個參數為n, fun_2的第二個參數由調用f4的第一個參數(_1)指定。
    f4(m); //print: m=3,n=4
    cout<<"m="<<m<<endl;//m=3  說明:bind對於不事先綁定的參數,通過std::placeholders傳遞的參數是通過引用傳遞的,如m
    cout<<"n="<<n<<endl;//n=3  說明:bind對於預先綁定的函數參數是通過值傳遞的,如n
    
    A a;
    //f5的類型為 function<void(int, int)>
    auto f5 = std::bind(&A::fun_3, a,placeholders::_1,placeholders::_2); //使用auto關鍵字
    f5(10,20);//調用a.fun_3(10,20),print: k=10,m=20

    std::function<void(int,int)> fc = std::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2);
    fc(10,20);   //調用a.fun_3(10,20) print: k=10,m=20 
    return 0; 
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM