อะไรคือความแตกต่างระหว่างคลาสเทมเพลตและเทมเพลตคลาส
อะไรคือความแตกต่างระหว่างคลาสเทมเพลตและเทมเพลตคลาส
คำตอบ:
นี่เป็นจุดทั่วไปของความสับสนสำหรับหลาย ๆ คน (รวมถึงหน้า Generic Programming บน Wikipedia บทแนะนำ C ++ และคำตอบอื่น ๆ ในหน้านี้) เท่าที่เกี่ยวข้องกับ C ++ ไม่มี "คลาสเทมเพลต" มีเพียง "เทมเพลตคลาส" เท่านั้น วิธีอ่านวลีนั้นคือ "เทมเพลตสำหรับคลาส" ซึ่งตรงข้ามกับ "เทมเพลตฟังก์ชัน" ซึ่งเป็น "เทมเพลตสำหรับฟังก์ชัน" อีกครั้ง: คลาสไม่ได้กำหนดแม่แบบแม่แบบกำหนดคลาส (และฟังก์ชัน) ตัวอย่างเช่นนี้เป็นแม่แบบโดยเฉพาะแม่แบบชั้นแต่มันเป็นไม่ได้ชั้นเรียน :
template<typename T> class MyClassTemplate
{
...
};
การประกาศMyClassTemplate<int> เป็นคลาสหรืออวดอ้างคลาสที่ยึดตามเทมเพลต ไม่มีคุณสมบัติพิเศษของคลาสที่ยึดตามเทมเพลตเทียบกับคลาสที่ไม่ได้ใช้เทมเพลต คุณสมบัติพิเศษของแม่ตัวเอง
วลี "template class" ไม่มีความหมายเนื่องจากคำว่า "template" ไม่มีความหมายเป็นคำคุณศัพท์เมื่อใช้กับคำนาม "class" เท่าที่ C ++ เกี่ยวข้อง มันแสดงถึงการมีอยู่ของคลาสที่เป็น (หรือกำหนด) แม่แบบซึ่งไม่ใช่แนวคิดที่มีอยู่ใน C ++
ฉันเข้าใจถึงความสับสนทั่วไปเนื่องจากน่าจะเป็นไปตามข้อเท็จจริงที่ว่าคำที่ปรากฏในลำดับ "template class" ในภาษาจริงซึ่งเป็นเรื่องราวอื่น ๆ ทั้งหมด
Bjarne Stroustrup ผู้สร้าง C ++ กล่าวในหนังสือของเขาThe C ++ Programming Language 4th edition , 23.2.1 การกำหนดเทมเพลท:
มีคนที่ทำให้ความแตกต่างความหมายระหว่างคำที่มีแม่แบบชั้นเรียนและแม่แบบเรียน ฉันไม่; มันจะละเอียดเกินไป: โปรดพิจารณาคำเหล่านั้นแทนกันได้ ในทำนองเดียวกันผมคิดว่าฟังก์ชั่นแม่แบบกันกับฟังก์ชั่นแม่แบบ
ความแตกต่างก็คือคำว่า "template class" ไม่มีอยู่ใน C ++ Standard เป็นคำที่ผู้คนส่วนใหญ่คิดว่าคำว่า "แม่แบบคลาส" สร้างความสับสน (เช่น บริษัท Qt Nokia และเดิมชื่อ Trolltech)
มาตรฐานไม่มีแนวคิดเกี่ยวกับเรื่องนี้ดังนั้นจึงขึ้นอยู่กับคนอื่น ๆ ที่จะสร้างความแตกต่าง บางคนใช้คำพ้องความหมายและบางคนบอกว่าคำว่า "คลาสเทมเพลต" หมายถึงเทมเพลตคลาสที่สร้างอินสแตนซ์หรือเฉพาะอย่างชัดเจนซึ่งจะทำให้เทียบเท่ากับคำว่า "class template specialization" ตามประวัติศาสตร์แล้วมันมีความหมายนี้ ข้อเขียน Reference Manualกำหนดได้ที่หน้า 343
คลาสที่สร้างจากเทมเพลตคลาสเรียกว่าคลาสเทมเพลตเนื่องจากคลาสที่กำหนดโดยเฉพาะโดยมีtemplate-class-nameเป็นชื่อ
ไม่ใช่ขั้วแม่แบบชั้นชื่อเทียบเท่ากับที่ไม่ใช่ขั้วแม่แบบ-IDtemplate-name < arguments >ที่ใช้ในปัจจุบันมาตรฐานและลงมา
เพื่อให้คุณคุ้นเคยกับข้อกำหนดในปัจจุบันซึ่งสำคัญกว่าการใช้คำศัพท์เก่าที่น่าสงสัย
// (1) defines a class template
template<typename T> class A { };
// (2) defines a class template explicit specialization
template<> class A<int> { };
// (3) defines a class template partial specialization
template<typename T> class A<T*> { };
// (4) explicitly instantiates A<char>.
template class A<char>;
// (5) implicitly instantiates A<short> (because of the member declaration)
struct D { A<short> a; };
คลาสเทมเพลตเกี่ยวข้องกับรูปแบบการออกแบบวิธีเทมเพลตในขณะที่เทมเพลตคลาสเป็นเพียงเทมเพลตคลาส "เติมในช่องว่าง"
เทมเพลตคลาสคือเทมเพลตที่ใช้ในการสร้างคลาสในขณะที่คลาสเทมเพลตคือคลาสที่สร้างโดยเทมเพลต
คลาสเทมเพลต: คลาสที่มีนิยามทั่วไปหรือคลาสที่มีพารามิเตอร์ซึ่งไม่ได้สร้างอินสแตนซ์จนกว่าไคลเอ็นต์จะให้ข้อมูล มันถูกอ้างถึงศัพท์แสงสำหรับเทมเพลตธรรมดาคลาสเดียวกับเทมเพลตคำนำหน้าและการใช้ T เทมเพลตคลาส: การสร้างคลาสแต่ละคลาสถูกระบุโดยเทมเพลตคลาสซึ่งเกือบจะคล้ายกับวิธีการสร้างอ็อบเจ็กต์แต่ละรายการโดยใช้คลาส มันถูกอ้างถึงวัตถุของคลาสเทมเพลต Ex- classname objectname (รายการอาร์กิวเมนต์)
เทมเพลตคลาสเป็นคลาสทั่วไปสำหรับออบเจ็กต์ประเภทต่างๆ โดยทั่วไปจะมีข้อกำหนดสำหรับการสร้างคลาสตามพารามิเตอร์ เมื่อใดก็ตามที่สร้างวัตถุใหม่คลาสใหม่จะเกิดขึ้นในหน่วยความจำเพื่อจุดประสงค์นั้น สิ่งนี้เรียกว่าการสร้างอินสแตนซ์เทมเพลตคลาสและแต่ละเวอร์ชันที่สร้างอินสแตนซ์ของคลาสเรียกว่าคลาสเทมเพลต
ดูบทความนี้ (จาก wg21 และตีพิมพ์ในปี 1992) :
คำศัพท์ที่สอดคล้องกัน
การโต้แย้งและความไม่เห็นด้วยส่วนใหญ่จนถึงปัจจุบันเกี่ยวข้องกับคำศัพท์ที่ใช้ในบทที่อธิบายแม่แบบ บ่อยที่สุดคือการใช้'function-template'และ'template-function'ที่แตกต่างกันเพื่อแสดงความคิดและความตั้งใจที่แตกต่างกัน เนื่องจากไม่มีการใช้การตั้งชื่อที่สอดคล้องกันผลลัพธ์คือความสับสนและการโต้แย้ง
สำหรับวัตถุประสงค์ของเอกสารนี้เป็นข้อเสนอสำหรับการนำไปใช้อย่างเป็นทางการโดยคณะกรรมการในการอภิปรายเกี่ยวกับแม่แบบและเพื่อวัตถุประสงค์ในการชี้แจงเอกสาร ฉันขอเสนอให้เราใช้การทำให้เป็นทางการโดยที่'-template' ต่อท้ายจะอธิบายถึงชุดประเภทหรือฟังก์ชันที่อธิบายโดยเทมเพลต และที่นำหน้า 'template-'ใช้เพื่ออธิบายนิยามเทมเพลตของส่วนหนึ่งของ'-template'เช่น a
'template-member-function'. ดังนั้น: -
- 'function-template':ชุดของฟังก์ชันที่อธิบายโดยเทมเพลตซึ่งเป็นพารามิเตอร์สำหรับข้อมูลบางประเภทที่ให้ไว้เป็นอาร์กิวเมนต์ของเทมเพลตนั้น ตัวอย่างเช่น :-
template<class T> int nullcheck( T* pT )
{ return ( pT != 0 ); }
- 'class-template':ชุดของคลาสที่อธิบายโดยเทมเพลตซึ่งเป็นพารามิเตอร์สำหรับข้อมูลบางประเภทที่ให้ไว้เป็นอาร์กิวเมนต์ของเทมเพลตนั้น ตัวอย่างเช่น :-
template<class T> class S {
int i;
public:
int sep_member();
int imm_member()
{ return 2; }
}
- 'template-function':ไม่อนุญาตให้ใช้คำนี้อีกต่อไป **
'template-class':ไม่อนุญาตให้ใช้คำนี้ **
'member-function-template':ไม่อนุญาตให้ใช้คำนี้เนื่องจากอธิบายถึงคุณสมบัติที่ไม่ได้รับการสนับสนุนโดยข้อกำหนดของเทมเพลต การใช้หลักการคำศัพท์ข้างต้นนี้จะอธิบายถึงสมาชิกของเทมเพลตที่ไม่ใช่คลาสซึ่งมีคำจำกัดความว่าเป็นเทมเพลต ตัวอย่างเช่น :-
class Normal { public:
template<class T> int foo(T*pT)
{ return ( pT == 0 ); }
};
อย่างไรก็ตามเนื่องจากขณะนี้เทมเพลตถูก จำกัด ไว้ในขอบเขตส่วนกลางเทมเพลตดังกล่าวจึงไม่ถูกต้อง
- 'template-static-member-function':
- 'template-member-function':
- 'template-static-member':
- 'template-static-data-member ' template-member ': เงื่อนไขทางเลือกสำหรับคำจำกัดความของสมาชิกที่ปรากฏแยกจาก' class-template 'ที่เป็นสมาชิก ตัวอย่างเช่น :-
template<class T> int S<T>::sep_member()
{ return i; }
Normalคลาสที่คุณอธิบายข้างต้น: ฉันไม่ทราบว่าแม่แบบสมาชิกฟังก์ชันดังกล่าวถูกห้าม เป็นที่ยอมรับโดยคอมไพเลอร์ทั้งหมดที่ฉันพยายาม ฉันขาดอะไรไป?