函數(shù)的定義
[修飾符] <返回類型> <函數(shù)名>(<形式參數(shù)列表>)[override] [const] [final]
??返回類型是必須的后众,當沒有返回類型的時候就用void代替,如果參數(shù)個數(shù)超過1渡八,則用逗號分隔參數(shù)列表,參數(shù)列表可以為空碾盐。
默認參數(shù)
C++中可以在函數(shù)聲明時為參數(shù)提供一個默認值,當函數(shù)調(diào)用時沒有指定這個參數(shù)的值锁摔,編譯器會自動用默認值代替一旦在一個函數(shù)調(diào)用中開始使用默認參數(shù)值廓旬,那么這個參數(shù)后的所有參數(shù)都必須使用默認參數(shù)
void myPrint(int x = 3)
{
printf("x:%d", x);
}
函數(shù)重載(Overroad)
??函數(shù)重載(Function Overload)用同一個函數(shù)名定義不同的函數(shù),當函數(shù)名和不同的參數(shù)搭配時函數(shù)的含義不同哼审。 函數(shù)重載至少滿足下面的一個條件:1.參數(shù)個數(shù)不同谐腰。 2.參數(shù)類型不同。3.參數(shù)順序不同涩盾。
class foo
{
public:
int add(int a,int b)
{
return a+b;
}
float add(float a, float b)
{
return a+b;
}
};
函數(shù)的返回值不作為區(qū)分重載函數(shù)的的條件十气。
float add(int a, int b)
{
return a+b;
} //編譯錯誤
override
??如果不使用override,當你手一抖春霍,將foo()寫成了f00()會怎么樣呢砸西?結(jié)果是編譯器并不會報錯,因為它并不知道你的目的是重寫虛函數(shù)址儒,而是把它當成了新的函數(shù)芹枷。如果這個虛函數(shù)很重要的話,那就會對整個程序不利莲趣。所以鸳慈,override的作用就出來了,它指定了子類的這個虛函數(shù)是重寫的父類的喧伞,如果你名字不小心打錯了的話走芋,編譯器是不會編譯通過的.
class A
{
virtual void foo();
};
class B :public A
{
//void fo0();
void fo0() override; //會編譯報錯
};
virtual 虛函數(shù)
??被virtual關(guān)鍵字修飾的成員函數(shù)绩郎,就是虛函數(shù)。虛函數(shù)的作用翁逞,用專業(yè)術(shù)語來解釋就是實現(xiàn)多態(tài)性 (Polymorphism)肋杖,多態(tài)性是將接口與實現(xiàn)進行分離,虛函數(shù)是C++ 的多態(tài)性的主要體現(xiàn)挖函,指向基類的指針在操作它的多態(tài)類對象時状植,會根據(jù)不同的類對象,調(diào)用其相應(yīng)的函數(shù)怨喘。
class Parent {
public:
void func_one(){
cout<<"parent:func_one"<<endl;
}
virtual void func_two(){
cout<<"parent:func_two"<<endl;
}
};
class Child : public Parent{
public:
void func_one(){
cout<<"Child:func_one"<<endl;
}
virtual void func_two(){
cout<<"Child:func_two"<<endl;
}
};
int main() {
Child child;
Parent *c= &child;//指向子類的指針
c->func_one();
c->func_two();
Parent &p = child;//子類的引用
p.func_one();
p.func_two();
return 0;
}
打印結(jié)果:
parent:func_one
Child:func_two
parent:func_one
Child:func_two
??簡單總結(jié)就是:基類中將某方法定義為虛函數(shù)浅萧,則在派生類中,該方法仍為虛方法哲思。在使用時洼畅,定義基類類型的指針,使其指向派生類的對象棚赔,使用該指針調(diào)用某個方法帝簇,若該方法未被聲明為虛函數(shù),則調(diào)用的是指針類中的方法靠益,若該方法是虛函數(shù)丧肴,則調(diào)用的是指針指向?qū)ο箢愔械脑摲椒ā_@也即是動態(tài)聯(lián)編胧后。
虛函數(shù)使用原則:
1)當類不會用作基類時芋浮,成員函數(shù)不要聲明為virtual
2)當成員函數(shù)不重新定義基類的方法,成員函數(shù)不要聲明為virtual
inline內(nèi)聯(lián)函數(shù)
??內(nèi)聯(lián)函數(shù)由 編譯器處理壳快,直接將編譯后的函數(shù)體插入調(diào)用的地方纸巷。宏代碼片段 由預(yù)處理器處理, 進行簡單的文本替換眶痰,沒有任何編譯過程
#include "iostream"
using namespace std;
#define MYFUNC(a, b) ((a) < (b) ? (a) : (b))
inline int myfunc(int a, int b)
{
return a < b ? a : b;
}
int main()
{
int a = 1;
int b = 3;
//int c = myfunc(++a, b); //頭疼系統(tǒng)
int c = MYFUNC(++a, b);
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
system("pause");
return 0;
}
??編譯器對于內(nèi)聯(lián)函數(shù)的限制并不是絕對的瘤旨,內(nèi)聯(lián)函數(shù)相對于普通函數(shù)的優(yōu)勢只是省去了函數(shù)調(diào)用時壓棧,跳轉(zhuǎn)和返回的開銷竖伯。因此存哲,當函數(shù)體的執(zhí)行開銷遠大于壓棧,跳轉(zhuǎn)和返回所用的開銷時七婴,那么內(nèi)聯(lián)將無意義祟偷。C++中內(nèi)聯(lián)編譯的限制:
1.不能存在任何形式的循環(huán)語句 2.不能存在過多的條件判斷語句 3.函數(shù)體不能過于龐大 4.不能對函數(shù)進行取址操作 5.函數(shù)內(nèi)聯(lián)聲明必須在調(diào)用語句之前。
靜態(tài)成員函數(shù)
??靜態(tài)成員函數(shù)數(shù)添加關(guān)鍵字static打厘,類的靜態(tài)成員(變量和方法)屬于類本身修肠,在類加載的時候就會分配內(nèi)存,可以通過類名直接去訪問婚惫;非靜態(tài)成員(變量和方法)屬于類的對象氛赐,所以只有在類的對象產(chǎn)生(創(chuàng)建類的實例)時才會分配內(nèi)存魂爪,然后通過類的對象(實例)去訪問。調(diào)用靜態(tài)成員函數(shù)如下:
<類名>::<靜態(tài)成員名>
??因為靜態(tài)成員函數(shù)屬于整個類艰管,在類實例化對象之前就已經(jīng)分配空間了滓侍,而類的非靜態(tài)成員必須在類實例化對象后才有內(nèi)存空間,所以靜態(tài)成員函數(shù)中牲芋,不能使用普通變量和成員函數(shù)撩笆,靜態(tài)成員函數(shù)與非靜態(tài)成員函數(shù)的根本區(qū)別是:非靜態(tài)成員函數(shù)有 this 指針,而靜態(tài)成員函數(shù)沒有 this 指針缸浦。
private:
int x;
public:
static void output()
{
cout<<x<<endl;
}
};
//error: invalid use of member 'x' in static member function
友元函數(shù)
friend <返回類型> <函數(shù)名> (<參數(shù)列表>);
??友元函數(shù)是可以直接訪問類的私有成員的非成員函數(shù)夕冲。它是定義在類外的普通函數(shù),它不屬于任何類裂逐,但需要在類的定義中加以聲明歹鱼,聲明時只需在友元的名稱前加上關(guān)鍵字friend。
??需要注意的是友元函數(shù)不是成員函數(shù)卜高,卻可以訪問類中的私有成員弥姻。友元的作用在于提高程序的運行效率(即減少了類型檢查和安全性檢查等都需要的時間開銷),同時它破壞了類的封裝性和隱藏性掺涛,使得非成員函數(shù)可以訪問類的私有成員庭敦。
Point::Point(int currX, int currY)
{
x = currX;
y = currY;
}
double distance(const Point &a,const Point &b)
{
double length;
length=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); //它可以引用類中的私有成員
return length;
}
int main()
{
Point p1(0,3), p2(4,0);
cout<<distance(p1,p2)<<endl;
}