สำหรับการทำความเข้าใจเทมเพลตการเข้าใจคำศัพท์นั้นเป็นประโยชน์อย่างมากเพราะวิธีที่คุณพูดเกี่ยวกับเทมเพลตจะเป็นตัวกำหนดวิธีคิดเกี่ยวกับเทมเพลตเหล่านี้
โดยเฉพาะArea
ไม่ใช่คลาสเทมเพลต แต่เป็นเทมเพลตคลาส นั่นคือมันเป็นเทมเพลตที่สามารถสร้างคลาสได้ Area<int>
เป็นคลาสดังกล่าว ( ไม่ใช่วัตถุ แต่แน่นอนคุณสามารถสร้างวัตถุจากคลาสนั้นด้วยวิธีเดียวกับที่คุณสามารถสร้างวัตถุจากคลาสอื่น ๆ ) Area<char>
อีกระดับดังกล่าวจะเป็น โปรดทราบว่าคลาสเหล่านี้เป็นคลาสที่แตกต่างกันโดยสิ้นเชิงซึ่งไม่มีอะไรเหมือนกันยกเว้นความจริงที่ว่าคลาสเหล่านี้ถูกสร้างขึ้นจากเทมเพลตคลาสเดียวกัน
เนื่องจากArea
ไม่ใช่คลาสคุณจึงไม่สามารถหาคลาสRectangle
จากคลาสได้ คุณสามารถได้รับคลาสจากคลาสอื่น (หรือหลายคลาส) เนื่องจากArea<int>
เป็นคลาสตัวอย่างเช่นคุณสามารถได้มาRectangle
จากมัน:
class Rectangle:
public Area<int>
{
// ...
};
เนื่องจากArea<int>
และArea<char>
เป็นคลาสที่แตกต่างกันคุณสามารถได้รับจากทั้งสองอย่างในเวลาเดียวกัน (อย่างไรก็ตามเมื่อเข้าถึงสมาชิกของพวกเขาคุณจะต้องจัดการกับความคลุมเครือ):
class Rectangle:
public Area<int>,
public Area<char>
{
// ...
};
Rectangle
แต่คุณจะต้องระบุประเภทจะได้รับจากเมื่อคุณกำหนด นี่เป็นความจริงไม่ว่าคลาสเหล่านั้นจะสร้างจากเทมเพลตหรือไม่ก็ตาม ออบเจ็กต์สองชิ้นของคลาสเดียวกันไม่สามารถมีลำดับชั้นการสืบทอดที่แตกต่างกันได้
สิ่งที่ทำได้คือทำRectangle
เทมเพลตด้วย ถ้าคุณเขียน
template<typename T> class Rectangle:
public Area<T>
{
// ...
};
คุณมีเทมเพลต Rectangle
จากการที่คุณจะได้รับในชั้นเรียนRectangle<int>
ที่มาจากArea<int>
และระดับที่แตกต่างกันซึ่งเกิดขึ้นจากRectangle<char>
Area<char>
อาจเป็นไปได้ว่าคุณต้องการมีแบบเดี่ยว Rectangle
เพื่อให้คุณสามารถส่งผ่านทุกประเภทRectangle
ไปยังฟังก์ชันเดียวกัน (ซึ่งตัวเองไม่จำเป็นต้องทราบประเภทพื้นที่) เนื่องจากRectangle<T>
คลาสที่สร้างขึ้นโดยการสร้างอินสแตนซ์เทมเพลตRectangle
นั้นเป็นอิสระจากกันอย่างเป็นทางการจึงไม่ได้ผลเช่นนั้น อย่างไรก็ตามคุณสามารถใช้ประโยชน์จากการสืบทอดหลายรายการได้ที่นี่:
class Rectangle // not inheriting from any Area type
{
// Area independent interface
};
template<typename T> class SpecificRectangle:
public Rectangle,
public Area<T>
{
// Area dependent stuff
};
void foo(Rectangle&); // A function which works with generic rectangles
int main()
{
SpecificRectangle<int> intrect;
foo(intrect);
SpecificRectangle<char> charrect;
foo(charrect);
}
หากเป็นสิ่งสำคัญที่ยาสามัญของคุณRectangle
มาจากยาสามัญArea
คุณสามารถทำเคล็ดลับเดียวกันได้Area
เช่นกัน:
class Area
{
// generic Area interface
};
class Rectangle:
public virtual Area // virtual because of "diamond inheritance"
{
// generic rectangle interface
};
template<typename T> class SpecificArea:
public virtual Area
{
// specific implementation of Area for type T
};
template<typename T> class SpecificRectangle:
public Rectangle, // maybe this should be virtual as well, in case the hierarchy is extended later
public SpecificArea<T> // no virtual inheritance needed here
{
// specific implementation of Rectangle for type T
};