運行期多態(虛函數)和編譯器多態(模板)
運行期多態的說明示例:
class Animal //基類
{
public :
virtual void shout() = 0;
};
class Dog :public Animal
{
public:
virtual void shout(){ cout << "汪汪!"<<endl; }
};
class Cat :public Animal
{
public:
virtual void shout(){ cout << "喵喵~"<<endl; }
};
void main()
{
Animal * anim1 = new Dog;
Animal * anim2 = new Cat;
//藉由指針(或引用)調用的接口,在運行期確定指針(或引用)所指對象的真正類型,調用該類型對應的接口--運行期多態
anim1->shout();
anim2->shout();
//delete 對象
...
}
編譯期多態的說明示例:
class Animal
{
public :
void shout() { cout << "發出動物的叫聲" << endl; };
};
class Dog
{
public:
void shout(){ cout << "汪汪!"<<endl; }
};
class Cat
{
public:
void shout(){ cout << "喵喵~"<<endl; }
};
template <typename T>
void animalShout(T & t)
{
t.shout();//在編譯期間,編譯器推斷出模板參數,因此確定調用的shout是哪個具體類型的接口。--編譯期多態
}
int main()
{
Animal anim;
Dog dog;
Cat cat;
animalShout(anim);
animalShout(dog);
animalShout(cat);
}
顯式接口(class)和隱式接口(template)
組成 | 什麼時候完成檢查 |
---|---|
顯式接口 | 函數的簽名式(函數名稱,參數類型、返回類型) |
隱式接口 | 有效表達式 |
顯式接口的說明示例:
class widget{
public:
widget();
virtual ~widget();
virtual std::size_t size() const;
void swap(widget& other);
};
//其public接口由一個構造函數、一個析構函數、size函數、swap函數及其參數類型、返回類型、常量性構成。也包括編譯器產生的copy函數(copy構造函數和copy assignment操作符)
隱式接口的說明示例:
template<typename T>
void dofun(T& w)
{
if(w.size() > 10 && w != value){...}
}
//T必須支持size成員函數,然而這個函數也可能從base class繼承。這個成員函數不需返回一個整數值,甚至不需返回一個數值類型。就此而言,甚至不需要返回一個定義有operator>的類型!唯一需要的是返回一個類型爲X的對象,X對象加上int必須能調用一個operator>。
//同樣的道理,T並不需要支持operator!=,因爲operator!=接受一個類型爲X的對象和一個類型爲Y的對象,T可被轉換爲X而value的類型可被轉換爲Y,這樣就可以有效調用operator!=