㈠ c++最簡單的多態例子,class A.classb
C++中的多態(雖然多態不是C++所特有的,但是C++中的多態確實是很特殊的)分為靜多態和動多態(也就是靜態綁定和動態綁定兩種現象),靜動的區別主要在於這種綁定發生在編譯期還是運行期,發生在編譯期的是靜態綁定,也就是靜多態;發生在運行期的則是動態綁定,也就是動多態。
靜多態可以通過模板和函數重載來實現(之所說C++中的多態主要還是因為模板這個東西),下面舉兩個例子:
1)函數模板
template <typename T>
T max(const T& lsh, const T& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
返回兩個任意類型對象的最大值(對象),前提是該類型能夠使用>運算符進行比較,並且返回值是bool類型。
使用:
int a = 3; int b = 4;
cout << max(a, b) << endl;
float c = 2.4; float d = 1.2;
cout << max(c, d) << endl;
輸出結果為:
4
2.4
這種綁定發生在編譯期,這是由於模板的實例化是發生在編譯期的,即在編譯時編譯器發現你調用max(a, b)時就自動生成一個函數
int max(const int& lsh, const int& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
即將所有的T替換成int;
當你調用max(c, d)時就自動生成一個函數
float max(const float& lsh, const float& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
之所以說開始的函數定義是函數模板,就是因為他就像個模子似的,你可以用鋁作為原料也可以用石膏或者銅。
2)函數重載:
int max (int a, int b)
{
return (a > b) ? a : b;
}
int max (int a, int b, int c)
{
return max(max(a, b), c);
}
兩個函數名稱一樣,參數類型或個數不完全相同,返回值一樣(這個不重要)。
使用:
int a = 3, b = 4, c = 5;
cout << max(a, b) << endl;
cout << max(a, b, c) << endl;
輸出結果為:
4
5
確定函數的過程也發生在編譯器,當你使用max(a, b),編譯器發現只有兩個參數,那麼就調用只有兩個參數的函數版本,當使用max(a, b, c)時,編譯器則使用有3個參數的版本。
通過上面的兩個例子,你還可以使用更為方便的模板函數重載:
template <typename T>
T max(const T& lsh, const T& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
template <typename T>
T max(const T& a, const T& b, const T& c)
{
return max(max(a, b), c);
}
使用
float a = 3.6, b = 1.2, c = 7.8;
cout << max(a, b, c) << endl;
輸出:
7.8
通過參數個數和類型,編譯器自動生成和調用對應得函數版本!
動多態則是通過繼承、虛函數(virtual)、指針來實現。
class A {
public:
virtual void func() const {
coust << 「A::func()」 << endl;
}
}
class B : public A {
public:
virtual void func() const {
coust << 「B::func()」 << endl;
}
}
使用:
A a* = B();
a->func();
輸出:
B::func()
編譯期是不調用任何函數的,編譯器編譯到a->func()時只是檢查有沒有語法問題,經過檢查沒有。編譯器並不知道調用的是A版本的func()還是B版本的func(),由於a是一個指向B對象的指針,所以a只知道它指向的是一個A類型(或者能轉換成A類型)的對象。通常集成體系就說明了(由於是公有繼承)B是一種A。在運行期,a要調用a所指向對象的func()函數,就對它指向的對象下達調用func()的命令,結果a所指向的是一個B對象,這個對象就調用了自己版本(B版)的func()函數,所以輸出時B::func()
總結:
在編譯期決定你應該調用哪個函數的行為是靜態綁定(static-binding),這種現象就是靜多態。
在運行期決定應該調用哪中類型對象的函數的行為是動態綁定(dynamic-binding),這種現象就是動多態
㈡ java中多態是什麼意思
多態(Polymorphism)按字面的意思就是「多種狀態」。在面向對象語言中,介面的多種不同的實現方式即為多態。引用Charlie Calverts對多態的描述——多態性是允許你將父對象設置成為一個或更多的他的子對象相等的技術,賦值之後,
父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作(摘自「Delphi4編程技術內幕」)。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。多態性在Object Pascal和C++中都是通過虛函數實現的。
多態指同一個實體同時具有多種形式。它是面向對象程序設計(OOP)的一個重要特徵。如果一個語言只支持類而不支持多態,只能說明它是基於對象的,而不是面向對象的。C++中的多態性具體體現在運行和編譯兩個方面。
運行時多態是動態多態,其具體引用的對象在運行時才能確定。編譯時多態是靜態多態,在編譯時就可以確定對象使用的形式。
多態:同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。在運行時,可以通過指向基類的指針,來調用實現派生類中的方法。
C++中,實現多態有以下方法:虛函數,抽象類,覆蓋,模板(重載和多態無關)。
OC中的多態:不同對象對同一消息的不同響應.子類可以重寫父類的方法
多態就是允許方法重名 參數或返回值可以是父類型傳入或返回。
(2)模板是編譯時多態的一個例子擴展閱讀:
把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。
賦值之後,父類型的引用就可以根據當前賦值給它的子對象的特性以不同的方式運作。也就是說,父親的行為像兒子,而不是兒子的行為像父親。
比如從某個基類派生出多個子類,其基類有一個虛方法Tdoit,然後其子類也有這個方法,但行為不同,然後這些子類對象中的任何一個可以賦給其基類對象的引用,或者說將子對象地址賦給基類指針,這樣其基類的對象就可以執行不同的操作了。
實際上你是在通過其基類的引用來訪問其子類對象的,你要做的就是一個賦值操作。
使用繼承性的結果就是當創建了一個類的家族,在認識這個類的家族時,就是把子類的對象當作基類的對象,這種認識又叫作upcasting(向上轉型)。這樣認識的重要性在於:我們可以只針對基類寫出一段程序,但它可以適應於這個類的家族,
因為編譯器會自動找出合適的對象來執行操作。這種現象又稱為多態性。而實現多態性的手段又叫稱動態綁定(dynamic binding)。
㈢ C++語言中的多態性是在編譯時通過CCCCCC和模板體現的是什麼意思
咬文嚼字幹嘛,中文寫的一些書都是翻譯過來的,質量不高。
多態 我都忘了專業術語了,應該包括重載,主要就是個名字mangling(不會翻譯)
虛函數:看下深度探索c++對象模型,你就大部分都懂了。
模板那叫參數多態吧:主要也就是個實例化
懂了就懂了,沒懂就沒懂。沒懂精髓,知道這些表述又有啥用。個人理解,勿噴~~
㈣ 編譯時多態性使用什麼獲得!A重載函數B繼承C虛函數D.B和C
函數重載和模板。就這題來說選A。
繼承和虛函數對應的多態需要在運行的時候才能確定具體對象,所以不屬於編譯時多態。
函數重載是讓一個函數名對應多個函數,編譯器會根據調用時候的特徵確定要調用的函數,不需要再運行時處理。
而模板是讓一個一個類型模板或者函數模板對應多個類型或者函數,編譯器根據對模板實例化是使用的參數生成具體的類和函數,也不是在運行時進行的。
另外注意模板變數不屬於多態范疇。
㈤ 什麼叫做多態性 在C++中是如何實現多態的
C++中的多態(雖然多態不是C++所特有的,但是C++中的多態確實是很特殊的)分為靜多態和動多態(也就是靜態綁定和動態綁定兩種現象),靜動的區別主要在於這種綁定發生在編譯期還是運行期,發生在編譯期的是靜態綁定,也就是靜多態;發生在運行期的則是動態綁定,也就是動多態。
靜多態可以通過模板和函數重載來實現(之所說C++中的多態主要還是因為模板這個東西),下面舉兩個例子:
1)函數模板
template <typename T>
T max(const T& lsh, const T& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
返回兩個任意類型對象的最大值(對象),前提是該類型能夠使用>運算符進行比較,並且返回值是bool類型。
使用:
int a = 3; int b = 4;
cout << max(a, b) << endl;
float c = 2.4; float d = 1.2;
cout << max(c, d) << endl;
輸出結果為:
4
2.4
這種綁定發生在編譯期,這是由於模板的實例化是發生在編譯期的,即在編譯時編譯器發現你調用max(a, b)時就自動生成一個函數
int max(const int& lsh, const int& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
即將所有的T替換成int;
當你調用max(c, d)時就自動生成一個函數
float max(const float& lsh, const float& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
之所以說開始的函數定義是函數模板,就是因為他就像個模子似的,你可以用鋁作為原料也可以用石膏或者銅。
2)函數重載:
int max (int a, int b)
{
return (a > b) ? a : b;
}
int max (int a, int b, int c)
{
return max(max(a, b), c);
}
兩個函數名稱一樣,參數類型或個數不完全相同,返回值一樣(這個不重要)。
使用:
int a = 3, b = 4, c = 5;
cout << max(a, b) << endl;
cout << max(a, b, c) << endl;
輸出結果為:
4
5
確定函數的過程也發生在編譯器,當你使用max(a, b),編譯器發現只有兩個參數,那麼就調用只有兩個參數的函數版本,當使用max(a, b, c)時,編譯器則使用有3個參數的版本。
通過上面的兩個例子,你還可以使用更為方便的模板函數重載:
template <typename T>
T max(const T& lsh, const T& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
template <typename T>
T max(const T& a, const T& b, const T& c)
{
return max(max(a, b), c);
}
使用
float a = 3.6, b = 1.2, c = 7.8;
cout << max(a, b, c) << endl;
輸出:
7.8
通過參數個數和類型,編譯器自動生成和調用對應得函數版本!
動多態則是通過繼承、虛函數(virtual)、指針來實現。
class A {
public:
virtual void func() const {
coust << 「A::func()」 << endl;
}
}
class B : public A {
public:
virtual void func() const {
coust << 「B::func()」 << endl;
}
}
使用:
A a* = B();
a->func();
輸出:
B::func()
編譯期是不調用任何函數的,編譯器編譯到a->func()時只是檢查有沒有語法問題,經過檢查沒有。編譯器並不知道調用的是A版本的func()還是B版本的func(),由於a是一個指向B對象的指針,所以a只知道它指向的是一個A類型(或者能轉換成A類型)的對象。通常集成體系就說明了(由於是公有繼承)B是一種A。在運行期,a要調用a所指向對象的func()函數,就對它指向的對象下達調用func()的命令,結果a所指向的是一個B對象,這個對象就調用了自己版本(B版)的func()函數,所以輸出時B::func()
總結:
在編譯期決定你應該調用哪個函數的行為是靜態綁定(static-binding),這種現象就是靜多態。
在運行期決定應該調用哪中類型對象的函數的行為是動態綁定(dynamic-binding),這種現象就是動多態!
註:由於這是我花了有限的時間總結的,語言應用能力比較差,還有比如類模板(靜多態和動多態組合的情況)都沒有說,最近比較忙,請見諒!
如果還不是很懂,我建議你看C++Primer 4th Edition,講的比較清晰,但是比較零散!
㈥ 請問 c++中 模板是 編譯時多態還是運行時多態,或者都不是,求解
是編譯時多態。所有的模板都是在編譯時產生對應的代碼,它沒有面向對象中的虛表,無法實現動態多態。
你仔細想一想,模板在應用時都必須指定確定的類型,而運行多態僅需指定一個基類就OK啦。
㈦ C++的多態性能應用在什麼地方舉個例子
C++多態技術
摘要
本文描述了C++中的各種多態性。重點闡述了面向對象的動態多態和基於模板的靜態多態,並初步探討了兩種技術的結合使用。
關鍵詞
多態 繼承 虛函數 模板 宏 函數重載 泛型編程 泛型模式
導言
多態(polymorphism)一詞最初來源於希臘語polumorphos,含義是具有多種形式或形態的情形。在程序設計領域,一個廣泛認可的定義是「一種將不同的特殊行為和單個泛化記號相關聯的能力」。和純粹的面向對象程序設計語言不同,C++中的多態有著更廣泛的含義。除了常見的通過類繼承和虛函數機制生效於運行期的動態多態(dynamic polymorphism)外,模板也允許將不同的特殊行為和單個泛化記號相關聯,由於這種關聯處理於編譯期而非運行期,因此被稱為靜態多態(static polymorphism)。
事實上,帶變數的宏和函數重載機制也允許將不同的特殊行為和單個泛化記號相關聯。然而,習慣上我們並不將它們展現出來的行為稱為多態(或靜態多態)。今天,當我們談及多態時,如果沒有明確所指,默認就是動態多態,而靜態多態則是指基於模板的多態。不過,在這篇以C++各種多態技術為主題的文章中,我們首先還是回顧一下C++社群爭論已久的另一種「多態」:函數多態(function polymorphism),以及更不常提的「宏多態(macro polymorphism)」。
函數多態
也就是我們常說的函數重載(function overloading)。基於不同的參數列表,同一個函數名字可以指向不同的函數定義:
// overload_poly.cpp
#include <iostream>
#include <string>
// 定義兩個重載函數
int my_add(int a, int b)
{
return a + b;
}
int my_add(int a, std::string b)
{
return a + atoi(b.c_str());
}
int main()
{
int i = my_add(1, 2); // 兩個整數相加
int s = my_add(1, "2"); // 一個整數和一個字元串相加
std::cout << "i = " << i << "\n";
std::cout << "s = " << s << "\n";
}
根據參數列表的不同(類型、個數或兼而有之),my_add(1, 2)和my_add(1, "2")被分別編譯為對my_add(int, int)和my_add(int, std::string)的調用。實現原理在於編譯器根據不同的參數列表對同名函數進行名字重整,而後這些同名函數就變成了彼此不同的函數。比方說,也許某個編譯器會將my_add()函數名字分別重整為my_add_int_int()和my_add_int_str()。
宏多態
帶變數的宏可以實現一種初級形式的靜態多態:
// macro_poly.cpp
#include <iostream>
#include <string>
// 定義泛化記號:宏ADD
#define ADD(A, B) (A) + (B);
int main()
{
int i1(1), i2(2);
std::string s1("Hello, "), s2("world!");
int i = ADD(i1, i2); // 兩個整數相加
std::string s = ADD(s1, s2); // 兩個字元串「相加」
std::cout << "i = " << i << "\n";
std::cout << "s = " << s << "\n";
}
當程序被編譯時,表達式ADD(i1, i2)和ADD(s1, s2)分別被替換為兩個整數相加和兩個字元串相加的具體表達式。整數相加體現為求和,而字元串相加則體現為連接。程序的輸出結果符合直覺:
1 + 2 = 3
Hello, + world! = Hello, world!
動態多態
這就是眾所周知的的多態。現代面向對象語言對這個概念的定義是一致的。其技術基礎在於繼承機制和虛函數。例如,我們可以定義一個抽象基類Vehicle和兩個派生於Vehicle的具體類Car和Airplane:
// dynamic_poly.h
#include <iostream>
// 公共抽象基類Vehicle
class Vehicle
{
public:
virtual void run() const = 0;
};
// 派生於Vehicle的具體類Car
class Car: public Vehicle
{
public:
virtual void run() const
{
std::cout << "run a car\n";
}
};
// 派生於Vehicle的具體類Airplane
class Airplane: public Vehicle
{
public:
virtual void run() const
{
std::cout << "run a airplane\n";
}
};
客戶程序可以通過指向基類Vehicle的指針(或引用)來操縱具體對象。通過指向基類對象的指針(或引用)來調用一個虛函數,會導致對被指向的具體對象之相應成員的調用:
// dynamic_poly_1.cpp
#include <iostream>
#include <vector>
#include "dynamic_poly.h"
// 通過指針run任何vehicle
void run_vehicle(const Vehicle* vehicle)
{
vehicle->run(); // 根據vehicle的具體類型調用對應的run()
}
int main()
{
Car car;
Airplane airplane;
run_vehicle(&car); // 調用Car::run()
run_vehicle(&airplane); // 調用Airplane::run()
}
此例中,關鍵的多態介面元素為虛函數run()。由於run_vehicle()的參數為指向基類Vehicle的指針,因而無法在編譯期決定使用哪一個版本的run()。在運行期,為了分派函數調用,虛函數被調用的那個對象的完整動態類型將被訪問。這樣一來,對一個Car對象調用run_vehicle(),實際上將調用Car::run(),而對於Airplane對象而言將調用Airplane::run()。
或許動態多態最吸引人之處在於處理異質對象集合的能力:
// dynamic_poly_2.cpp
#include <iostream>
#include <vector>
#include "dynamic_poly.h"
// run異質vehicles集合
void run_vehicles(const std::vector<Vehicle*>& vehicles)
{
for (unsigned int i = 0; i < vehicles.size(); ++i)
{
vehicles[i]->run(); // 根據具體vehicle的類型調用對應的run()
}
}
int main()
{
Car car;
Airplane airplane;
std::vector<Vehicle*> v; // 異質vehicles集合
v.push_back(&car);
v.push_back(&airplane);
run_vehicles(v); // run不同類型的vehicles
}
在run_vehicles()中,vehicles[i]->run()依據正被迭代的元素的類型而調用不同的成員函數。這從一個側面體現了面向對象編程風格的優雅。
靜態多態
如果說動態多態是通過虛函數來表達共同介面的話,那麼靜態多態則是通過「彼此單獨定義但支持共同操作的具體類」來表達共同性,換句話說,必須存在必需的同名成員函數。
我們可以採用靜態多態機制重寫上一節的例子。這一次,我們不再定義vehicles類層次結構,相反,我們編寫彼此無關的具體類Car和Airplane(它們都有一個run()成員函數):
// static_poly.h
#include <iostream>
//具體類Car
class Car
{
public:
void run() const
{
std::cout << "run a car\n";
}
};
//具體類Airplane
class Airplane
{
public:
void run() const
{
std::cout << "run a airplane\n";
}
};
run_vehicle()應用程序被改寫如下:
// static_poly_1.cpp
#include <iostream>
#include <vector>
#include "static_poly.h"
// 通過引用而run任何vehicle
template <typename Vehicle>
void run_vehicle(const Vehicle& vehicle)
{
vehicle.run(); // 根據vehicle的具體類型調用對應的run()
}
int main()
{
Car car;
Airplane airplane;
run_vehicle(car); // 調用Car::run()
run_vehicle(airplane); // 調用Airplane::run()
}
現在Vehicle用作模板參數而非公共基類對象(事實上,這里的Vehicle只是一個符合直覺的記號而已,此外別無它意)。經過編譯器處理後,我們最終會得到run_vehicle<Car>()和 run_vehicle<Airplane>()兩個不同的函數。這和動態多態不同,動態多態憑借虛函數分派機制在運行期只有一個run_vehicle()函數。
我們無法再透明地處理異質對象集合了,因為所有類型都必須在編譯期予以決定。不過,為不同的vehicles引入不同的集合只是舉手之勞。由於無需再將集合元素局限於指針或引用,我們現在可以從執行性能和類型安全兩方面獲得好處:
// static_poly_2.cpp
#include <iostream>
#include <vector>
#include "static_poly.h"
// run同質vehicles集合
template <typename Vehicle>
void run_vehicles(const std::vector<Vehicle>& vehicles)
{
for (unsigned int i = 0; i < vehicles.size(); ++i)
{
vehicles[i].run(); // 根據vehicle的具體類型調用相應的run()
}
}
int main()
{
Car car1, car2;
Airplane airplane1, airplane2;
std::vector<Car> vc; // 同質cars集合
vc.push_back(car1);
vc.push_back(car2);
//vc.push_back(airplane1); // 錯誤:類型不匹配
run_vehicles(vc); // run cars
std::vector<Airplane> vs; // 同質airplanes集合
vs.push_back(airplane1);
vs.push_back(airplane2);
//vs.push_back(car1); // 錯誤:類型不匹配
run_vehicles(vs); // run airplanes
}
兩種多態機制的結合使用
在一些高級C++應用中,我們可能需要結合使用動態多態和靜態多態兩種機制,以期達到對象操作的優雅、安全和高效。例如,我們既希望一致而優雅地處理vehicles的run問題,又希望「安全而高效」地完成給飛行器(飛機、飛艇等)進行「空中加油」這樣的高難度動作。為此,我們首先將上面的vehicles類層次結構改寫如下:
// dscombine_poly.h
#include <iostream>
#include <vector>
// 公共抽象基類Vehicle
class Vehicle
{
public:
virtual void run() const = 0;
};
// 派生於Vehicle的具體類Car
class Car: public Vehicle
{
public:
virtual void run() const
{
std::cout << "run a car\n";
}
};
// 派生於Vehicle的具體類Airplane
class Airplane: public Vehicle
{
public:
virtual void run() const
{
std::cout << "run a airplane\n";
}
void add_oil() const
{
std::cout << "add oil to airplane\n";
}
};
// 派生於Vehicle的具體類Airship
class Airship: public Vehicle
{
public:
virtual void run() const
{
std::cout << "run a airship\n";
}
void add_oil() const
{
std::cout << "add oil to airship\n";
}
};
我們理想中的應用程序可以編寫如下:
// dscombine_poly.cpp
#include <iostream>
#include <vector>
#include "dscombine_poly.h"
// run異質vehicles集合
void run_vehicles(const std::vector<Vehicle*>& vehicles)
{
for (unsigned int i = 0; i < vehicles.size(); ++i)
{
vehicles[i]->run(); // 根據具體的vehicle類型調用對應的run()
}
}
// 為某種特定的aircrafts同質對象集合進行「空中加油」
template <typename Aircraft>
void add_oil_to_aircrafts_in_the_sky(const std::vector<Aircraft>& aircrafts)
{
for (unsigned int i = 0; i < aircrafts.size(); ++i)
{
aircrafts[i].add_oil();
}
}
int main()
{
Car car1, car2;
Airplane airplane1, airplane2;
Airship airship1, airship2;
std::vector<Vehicle*> v; // 異質vehicles集合
v.push_back(&car1);
v.push_back(&airplane1);
v.push_back(&airship1);
run_vehicles(v); // run不同種類的vehicles
std::vector<Airplane> vp; // 同質airplanes集合
vp.push_back(airplane1);
vp.push_back(airplane2);
add_oil_to_aircrafts_in_the_sky(vp); // 為airplanes進行「空中加油」
std::vector<Airship> vs; // 同質airships集合
vs.push_back(airship1);
vs.push_back(airship2);
add_oil_to_aircrafts_in_the_sky(vs); // 為airships進行「空中加油」
}
我們保留了類層次結構,目的是為了能夠利用run_vehicles()一致而優雅地處理異質對象集合vehicles的run問題。同時,利用函數模板add_oil_to_aircrafts_in_the_sky<Aircraft>(),我們仍然可以處理特定種類的vehicles — aircrafts(包括airplanes和airships)的「空中加油」問題。其中,我們避開使用指針,從而在執行性能和類型安全兩方面達到了預期目標。
結語
長期以來,C++社群對於多態的內涵和外延一直爭論不休。在comp.object這樣的網路論壇上,此類話題爭論至今仍隨處可見。曾經有人將動態多態(dynamic polymorphism)稱為inclusion polymorphism,而將靜態多態(static polymorphism)稱為parametric polymorphism或parameterized polymorphism。
我注意到2003年斯坦福大學公開的一份C++ and Object-Oriented Programming教案中明確提到了函數多態概念:Function overloading is also referred to as function polymorphism as it involves one function having many forms。文後的「參考文獻」單元給出了這個網頁鏈接。
可能你是第一次看到宏多態(macro polymorphism)這個術語。不必訝異 — 也許我就是造出這個術語的「第一人」。顯然,帶變數的宏(或類似於函數的宏或偽函數宏)的替換機制除了免除小型函數的調用開銷之外,也表現出了類似的多態性。在我們上面的例子中,字元串相加所表現出來的符合直覺的連接操作,事實上是由底部運算符重載機制(operator overloading)支持的。值得指出的是,C++社群中有人將運算符重載所表現出來的多態稱為ad hoc polymorphism。
David Vandevoorde和Nicolai M. Josuttis在他們的著作C++ Templates: The Complete Guide一書中系統地闡述了靜態多態和動態多態技術。因為認為「和其他語言機制關系不大」,這本書沒有提及「宏多態」(以及「函數多態」)。(需要說明的是,筆者本人是這本書的繁體中文版譯者之一,本文正是基於這本書的第14章The Polymorphic Power of Templates編寫而成)
動態多態只需要一個多態函數,生成的可執行代碼尺寸較小,靜態多態必須針對不同的類型產生不同的模板實體,尺寸會大一些,但生成的代碼會更快,因為無需通過指針進行間接操作。靜態多態比動態多態更加類型安全,因為全部綁定都被檢查於編譯期。正如前面例子所示,你不可將一個錯誤的類型的對象插入到從一個模板實例化而來的容器之中。此外,正如你已經看到的那樣,動態多態可以優雅地處理異質對象集合,而靜態多態可以用來實現安全、高效的同質對象集合操作。
靜態多態為C++帶來了泛型編程(generic programming)的概念。泛型編程可以認為是「組件功能基於框架整體而設計」的模板編程。STL就是泛型編程的一個典範。STL是一個框架,它提供了大量的演算法、容器和迭代器,全部以模板技術實現。從理論上講,STL的功能當然可以使用動態多態來實現,不過這樣一來其性能必將大打折扣。
靜態多態還為C++社群帶來了泛型模式(generic patterns)的概念。理論上,每一個需要通過虛函數和類繼承而支持的設計模式都可以利用基於模板的靜態多態技術(甚至可以結合使用動態多態和靜態多態兩種技術)而實現。正如你看到的那樣,Andrei Alexandrescu的天才作品Modern C++ Design: Generic Programming and Design Patterns Applied(Addison-Wesley)和Loki程序庫已經走在了我們的前面。
㈧ c++中什麼是多態!
在C++中介面的多種不同的實現方式就是多態。
多態性是允許你將父對象設置成為一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。允許將子類類型的指針賦值給父類類型的指針。多態性在ObjectPascal和C++中都是通過虛函數實現的。
賦值之後,父類型的引用就可以根據當前賦值給它的子對象的特性以不同的方式運作。也就是說,父親的行為像兒子,而不是兒子的行為像父親。
(8)模板是編譯時多態的一個例子擴展閱讀
多態的使用
#include<iostream>
usingnamespacestd;
classA{
public:
virtualvoidPrint(){cout<<"A::Print"<<endl;}
};
classB:publicA{
public:
voidPrint(){cout<<"B::Print"<<endl;}
};
voidPrintlnfo(A&r){//傳參相當於:r=a(指向父類A的Print()虛函數);或者r=b(指向子類B的Print()虛函數);
r.Print();//多態,調用哪個Print,取決於r引用了哪個類的對象
}
intmain()
{
Aa;Bb;
Printlnfo(a);//輸出A::Print
Printlnfo(b);//輸出B::Print
return0;
}
㈨ 什麼是多態
多態首先是建立在繼承的基礎上的,先有繼承才能有多態。多態是指不同的子類在繼承父類後分別都重寫覆蓋了父類的方法,即父類同一個方法,在繼承的子類中表現出不同的形式。多態成立的另一個條件是在創建子類時候必須使用父類new子類的方式。
多態(Polymorphism)按字面的意思就是「多種狀態」。在面向對象語言中,介面的多種不同的實現方式即為多態。引用Charlie Calverts對多態的描述——多態性是允許你將父對象設置成為一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作(摘自「Delphi4編程技術內幕」)。
簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。多態性在Object Pascal和C++中都是通過虛函數實現的。
拓展資料:
多態指同一個實體同時具有多種形式。它是面向對象程序設計(OOP)的一個重要特徵。如果一個語言只支持類而不支持多態,只能說明它是基於對象的,而不是面向對象的。C++中的多態性具體體現在運行和編譯兩個方面。運行時多態是動態多態,其具體引用的對象在運行時才能確定。編譯時多態是靜態多態,在編譯時就可以確定對象使用的形式。
多態:同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。在運行時,可以通過指向基類的指針,來調用實現派生類中的方法。
C++中,實現多態有以下方法:虛函數,抽象類,覆蓋,模板(重載和多態無關)。
OC中的多態:不同對象對同一消息的不同響應.子類可以重寫父類的方法。
多態就是允許方法重名 參數或返回值可以是父類型傳入或返回。
多態也指生物學中腔腸動物的特殊的生活方式。水螅態與水母態的世代交替現象。
把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。
賦值之後,父類型的引用就可以根據當前賦值給它的子對象的特性以不同的方式運作。也就是說,父親的行為像兒子,而不是兒子的行為像父親。
使用繼承性的結果就是當創建了一個類的家族,在認識這個類的家族時,就是把子類的對象當作基類的對象,這種認識又叫作upcasting(向上轉型)。這樣認識的重要性在於:我們可以只針對基類寫出一段程序,但它可以適應於這個類的家族,因為編譯器會自動找出合適的對象來執行操作。這種現象又稱為多態性。而實現多態性的手段又叫稱動態綁定(dynamic binding)。
簡單的說,建立一個父類對象的引用,它所指對象可以是這個父類的對象,也可以是它的子類的對象。java中當子類擁有和父類同樣的函數,當通過這個父類對象的引用調用這個函數的時候,調用到的是子類中的函數。