1、 靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編:
• 聯(lián)編:是指一個(gè)計(jì)算機(jī)程序自身彼此關(guān)聯(lián)的過(guò)程。按聯(lián)編所進(jìn)行的階段不同,可分為兩種不同的聯(lián)編方法。一種是靜態(tài)聯(lián)編,一種是動(dòng)態(tài)聯(lián)編。
• 靜態(tài)聯(lián)編:聯(lián)編工作出現(xiàn)在編譯連接階段,這種聯(lián)編過(guò)程在程序開始運(yùn)行之前完成。
例如:一個(gè)靜態(tài)聯(lián)編的例子。
#include
class Point
{
public:
Point(double I,double j)
{ x=I;y=j;}
double Area(){return 0.0;}
private:
double x,y;
};
class Rectangle :public Point
{
public:
Rectangle(double i,double j,double k,double l);
Double Area()
{return w*h;}
private:
double w,h;
};
Rectangle::Rectangle(double i,double j
,double k,double l):point(i,j)
{
w=k;h=l;
}
void fun(point &s)
{
cout<
}
void main()
{
Rectangle rec(3.0,5.2,15.0,25.0);
Fun(rec);
}
分析程序:在 fun() 函數(shù)中, s 所引用對(duì)象執(zhí)行的 Area() 操作被關(guān)聯(lián)到 point::Area() 的實(shí)現(xiàn)代碼上。這是靜態(tài)聯(lián)編的結(jié)果。在程序編譯階段,對(duì) s 所引用 的對(duì)象所執(zhí)行 的 Area() 操作只能束定到 point 類的函數(shù)上。
所以執(zhí)行結(jié)果為: 0
• 動(dòng)態(tài)聯(lián)編:有時(shí)編譯程序在編譯階段,并不能確切知道將要調(diào)用的函數(shù),只有在程序執(zhí)行時(shí)才能確定將要調(diào)用的函數(shù),為此,要確切知道調(diào)用的函數(shù),要求聯(lián)編工作要在程序運(yùn)行時(shí)進(jìn)行,這種在程序運(yùn)行時(shí)進(jìn)行聯(lián)編工作被稱為動(dòng)態(tài)聯(lián)編。
動(dòng)態(tài)聯(lián)編是在虛函數(shù)的支持下實(shí)現(xiàn)的。
所以靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編也都屬于多態(tài)性,它們是在不同階段對(duì)不同實(shí)現(xiàn)進(jìn)行的選擇。
2、 虛函數(shù):(是成員函數(shù),且是非 static 的)
• 格式: virtual < 類型說(shuō)明符 >< 函數(shù)名 >(< 參數(shù)表 >)
• 說(shuō)明:①如果某類中的成員函數(shù)被說(shuō)明 為虛函數(shù),就意味著該成員函數(shù)在派生類中可能有不同的實(shí)現(xiàn)。當(dāng)使用這個(gè)成員函數(shù)操作 指針或引用 所標(biāo)識(shí)對(duì)象時(shí),對(duì)該成員函數(shù)調(diào)用采用動(dòng)態(tài)聯(lián)編方式,即在運(yùn)行時(shí)進(jìn)行束定。
• 態(tài)聯(lián)編只能通過(guò)指針或引用標(biāo)識(shí)對(duì)象來(lái)操作虛函數(shù)。若采用一般類型的標(biāo)識(shí)對(duì)象來(lái)操作虛函數(shù),則采用靜態(tài)聯(lián)編方式調(diào)用虛函數(shù)。
例如:一個(gè)動(dòng)態(tài)聯(lián)編的例子:
#include
class point
{
public:
point(double I,double j)
{x=I;y=j;}
virtual double Area()
{return 0.0;}
private:
double x,y;
};
class Rectangle:public point
{
public:
Rectangle(double I,double j,double k,double l);
Virtual double Area()
{
return w*h;
}
private:
ouble w,h;
};
Rectangle::Rectangle(double I,double j,
double k,double l):point(I,j)
{
w=k;h=l;
}
void fun(point &s) // 被動(dòng)態(tài)聯(lián)編
{
cout<
}
void main()
{
Rectangle rec(3.0,5.2,15.0,25.0);
Fun(rec);
}
輸出結(jié)果: 375
• 派生類中對(duì)基類的虛函數(shù)進(jìn)行替換時(shí),要求派生類中說(shuō)明的虛函數(shù)與基類中被替換的虛函數(shù)之間滿足如下條件:
• 與基類的虛函數(shù)有相同的參數(shù)個(gè)數(shù)。
• 其參數(shù)的類型與基類的虛函數(shù)的對(duì)應(yīng)參數(shù)類型相同。
• 其返回值或者與基類虛函數(shù)相同,或者都返回指針或引用。
滿足上述條件的派生類的成員函數(shù),自然是虛函數(shù),可以不加 virtual.
例如:分析下列程序輸出結(jié)果,并回答問(wèn)題:
#include
class A
{
public:
virtual void act1();
void act2()
{
act1();
}
};
void A::act1()
{ cout<<”A::act1() called.”<
class B:public A
{
public:
void act1();
}
void B::act1()
{cout<<”B::act1() called.”<
void main()
{
B b;
b.act2();
}
回答問(wèn)題:①該程序執(zhí)行后的輸出結(jié)果是什么?為什么?
答: B::act1() called.
因?yàn)?B 是 A 的派生類, act1() 是 A 類的虛函數(shù) , 類 B 中的 act1() 自然是虛函數(shù)。在 main() 函數(shù)中, b.act2(), 調(diào)用類 B 中的 act2() 函數(shù), B 是派生類,實(shí)際上調(diào)用 A::act2(), 而 A::act2() 函數(shù)的實(shí)現(xiàn)中調(diào)用 act1(), 由于有兩個(gè) act1() 函數(shù),并且是虛函數(shù),產(chǎn)生了動(dòng)態(tài)聯(lián)編,根據(jù)運(yùn)行情況,選擇了 B::act1();
• 如果將 A::act2() 的實(shí)現(xiàn)改為:
void A::act2()
{
this → act1();
}
輸出結(jié)果如何?
答: B::act1() called.
因?yàn)?this 是指向操作該成員函數(shù)的對(duì)象的指針。
• 如果將 A::act2() 的實(shí)現(xiàn)改為:
void A::act2()
{
a::act1();
}
輸出結(jié)果如何?
答: A::act1() called.
• 虛函數(shù)的限制:
一個(gè)類中將所有的成員函數(shù)都盡可能 地設(shè)置為虛函數(shù)總是有益的。它除了會(huì)增加一些系統(tǒng)開銷,沒(méi)有其他壞處。但是設(shè)置虛函數(shù)應(yīng)注意:
• 只有類的成員函數(shù)才能 說(shuō)明為虛函數(shù)。這是因?yàn)樘摵瘮?shù)僅使用于有繼承 關(guān)系的類對(duì)象,所以普通函數(shù)不能說(shuō)明為虛函數(shù)。
• 聯(lián)編:是指一個(gè)計(jì)算機(jī)程序自身彼此關(guān)聯(lián)的過(guò)程。按聯(lián)編所進(jìn)行的階段不同,可分為兩種不同的聯(lián)編方法。一種是靜態(tài)聯(lián)編,一種是動(dòng)態(tài)聯(lián)編。
• 靜態(tài)聯(lián)編:聯(lián)編工作出現(xiàn)在編譯連接階段,這種聯(lián)編過(guò)程在程序開始運(yùn)行之前完成。
例如:一個(gè)靜態(tài)聯(lián)編的例子。
#include
class Point
{
public:
Point(double I,double j)
{ x=I;y=j;}
double Area(){return 0.0;}
private:
double x,y;
};
class Rectangle :public Point
{
public:
Rectangle(double i,double j,double k,double l);
Double Area()
{return w*h;}
private:
double w,h;
};
Rectangle::Rectangle(double i,double j
,double k,double l):point(i,j)
{
w=k;h=l;
}
void fun(point &s)
{
cout<
}
void main()
{
Rectangle rec(3.0,5.2,15.0,25.0);
Fun(rec);
}
分析程序:在 fun() 函數(shù)中, s 所引用對(duì)象執(zhí)行的 Area() 操作被關(guān)聯(lián)到 point::Area() 的實(shí)現(xiàn)代碼上。這是靜態(tài)聯(lián)編的結(jié)果。在程序編譯階段,對(duì) s 所引用 的對(duì)象所執(zhí)行 的 Area() 操作只能束定到 point 類的函數(shù)上。
所以執(zhí)行結(jié)果為: 0
• 動(dòng)態(tài)聯(lián)編:有時(shí)編譯程序在編譯階段,并不能確切知道將要調(diào)用的函數(shù),只有在程序執(zhí)行時(shí)才能確定將要調(diào)用的函數(shù),為此,要確切知道調(diào)用的函數(shù),要求聯(lián)編工作要在程序運(yùn)行時(shí)進(jìn)行,這種在程序運(yùn)行時(shí)進(jìn)行聯(lián)編工作被稱為動(dòng)態(tài)聯(lián)編。
動(dòng)態(tài)聯(lián)編是在虛函數(shù)的支持下實(shí)現(xiàn)的。
所以靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編也都屬于多態(tài)性,它們是在不同階段對(duì)不同實(shí)現(xiàn)進(jìn)行的選擇。
2、 虛函數(shù):(是成員函數(shù),且是非 static 的)
• 格式: virtual < 類型說(shuō)明符 >< 函數(shù)名 >(< 參數(shù)表 >)
• 說(shuō)明:①如果某類中的成員函數(shù)被說(shuō)明 為虛函數(shù),就意味著該成員函數(shù)在派生類中可能有不同的實(shí)現(xiàn)。當(dāng)使用這個(gè)成員函數(shù)操作 指針或引用 所標(biāo)識(shí)對(duì)象時(shí),對(duì)該成員函數(shù)調(diào)用采用動(dòng)態(tài)聯(lián)編方式,即在運(yùn)行時(shí)進(jìn)行束定。
• 態(tài)聯(lián)編只能通過(guò)指針或引用標(biāo)識(shí)對(duì)象來(lái)操作虛函數(shù)。若采用一般類型的標(biāo)識(shí)對(duì)象來(lái)操作虛函數(shù),則采用靜態(tài)聯(lián)編方式調(diào)用虛函數(shù)。
例如:一個(gè)動(dòng)態(tài)聯(lián)編的例子:
#include
class point
{
public:
point(double I,double j)
{x=I;y=j;}
virtual double Area()
{return 0.0;}
private:
double x,y;
};
class Rectangle:public point
{
public:
Rectangle(double I,double j,double k,double l);
Virtual double Area()
{
return w*h;
}
private:
ouble w,h;
};
Rectangle::Rectangle(double I,double j,
double k,double l):point(I,j)
{
w=k;h=l;
}
void fun(point &s) // 被動(dòng)態(tài)聯(lián)編
{
cout<
}
void main()
{
Rectangle rec(3.0,5.2,15.0,25.0);
Fun(rec);
}
輸出結(jié)果: 375
• 派生類中對(duì)基類的虛函數(shù)進(jìn)行替換時(shí),要求派生類中說(shuō)明的虛函數(shù)與基類中被替換的虛函數(shù)之間滿足如下條件:
• 與基類的虛函數(shù)有相同的參數(shù)個(gè)數(shù)。
• 其參數(shù)的類型與基類的虛函數(shù)的對(duì)應(yīng)參數(shù)類型相同。
• 其返回值或者與基類虛函數(shù)相同,或者都返回指針或引用。
滿足上述條件的派生類的成員函數(shù),自然是虛函數(shù),可以不加 virtual.
例如:分析下列程序輸出結(jié)果,并回答問(wèn)題:
#include
class A
{
public:
virtual void act1();
void act2()
{
act1();
}
};
void A::act1()
{ cout<<”A::act1() called.”<
class B:public A
{
public:
void act1();
}
void B::act1()
{cout<<”B::act1() called.”<
void main()
{
B b;
b.act2();
}
回答問(wèn)題:①該程序執(zhí)行后的輸出結(jié)果是什么?為什么?
答: B::act1() called.
因?yàn)?B 是 A 的派生類, act1() 是 A 類的虛函數(shù) , 類 B 中的 act1() 自然是虛函數(shù)。在 main() 函數(shù)中, b.act2(), 調(diào)用類 B 中的 act2() 函數(shù), B 是派生類,實(shí)際上調(diào)用 A::act2(), 而 A::act2() 函數(shù)的實(shí)現(xiàn)中調(diào)用 act1(), 由于有兩個(gè) act1() 函數(shù),并且是虛函數(shù),產(chǎn)生了動(dòng)態(tài)聯(lián)編,根據(jù)運(yùn)行情況,選擇了 B::act1();
• 如果將 A::act2() 的實(shí)現(xiàn)改為:
void A::act2()
{
this → act1();
}
輸出結(jié)果如何?
答: B::act1() called.
因?yàn)?this 是指向操作該成員函數(shù)的對(duì)象的指針。
• 如果將 A::act2() 的實(shí)現(xiàn)改為:
void A::act2()
{
a::act1();
}
輸出結(jié)果如何?
答: A::act1() called.
• 虛函數(shù)的限制:
一個(gè)類中將所有的成員函數(shù)都盡可能 地設(shè)置為虛函數(shù)總是有益的。它除了會(huì)增加一些系統(tǒng)開銷,沒(méi)有其他壞處。但是設(shè)置虛函數(shù)應(yīng)注意:
• 只有類的成員函數(shù)才能 說(shuō)明為虛函數(shù)。這是因?yàn)樘摵瘮?shù)僅使用于有繼承 關(guān)系的類對(duì)象,所以普通函數(shù)不能說(shuō)明為虛函數(shù)。

