เหตุใดฉันจึงไม่สามารถเริ่มต้นstatic
สมาชิกข้อมูลในชั้นเรียนได้
มาตรฐาน C ++ อนุญาตให้มีการเตรียมใช้งานเฉพาะประเภทอินทิกรัลค่าคงที่คงที่หรือประเภทการแจงนับเท่านั้น นี่คือเหตุผลที่a
อนุญาตให้เริ่มต้นในขณะที่คนอื่นไม่ได้
อ้างอิง:
C ++ 03 9.4.2 สมาชิกข้อมูลคงที่
§4
หากสมาชิกข้อมูลคงที่เป็นชนิดการแจงนับ const หรือ const การประกาศในนิยามคลาสสามารถระบุค่าคงที่ - initializer ซึ่งจะต้องเป็นนิพจน์ค่าคงที่เชิงปริพันธ์ (5.19) ในกรณีนั้นสมาชิกสามารถปรากฏในนิพจน์ค่าคงที่อินทิกรัล สมาชิกจะยังคงถูกกำหนดในขอบเขตเนมสเปซหากใช้ในโปรแกรมและการกำหนดขอบเขตเนมสเปซจะต้องไม่มีตัวเริ่มต้น
ประเภทอินทิกรัลคืออะไร?
C ++ 03 3.9.1 ประเภทพื้นฐาน
§7
ประเภท bool, char, wchar_t และประเภทจำนวนเต็มที่ลงชื่อและไม่ได้ลงนามเรียกรวมกันว่าประเภทอินทิกรัล 43) คำพ้องความหมายสำหรับประเภทอินทิกรัลคือประเภทจำนวนเต็ม
เชิงอรรถ:
43)ดังนั้นการแจงนับ (7.2) จึงไม่เป็นส่วนประกอบ อย่างไรก็ตามการแจงนับสามารถเลื่อนระดับเป็น int ไม่ได้ลงนาม int ยาวหรือไม่ได้ลงนามยาวตามที่ระบุไว้ใน 4.5
วิธีแก้ปัญหา:
คุณสามารถใช้เคล็ดลับ enumเพื่อเริ่มต้นอาร์เรย์ภายในนิยามคลาสของคุณ
class A
{
static const int a = 3;
enum { arrsize = 2 };
static const int c[arrsize] = { 1, 2 };
};
เหตุใดมาตรฐานจึงไม่อนุญาตให้ทำเช่นนี้
Bjarne อธิบายสิ่งนี้อย่างเหมาะสมที่นี่ :
โดยทั่วไปคลาสจะถูกประกาศในไฟล์ส่วนหัวและโดยทั่วไปไฟล์ส่วนหัวจะรวมอยู่ในหน่วยการแปลจำนวนมาก อย่างไรก็ตามเพื่อหลีกเลี่ยงกฎตัวเชื่อมโยงที่ซับซ้อน C ++ ต้องการให้ทุกออบเจ็กต์มีนิยามเฉพาะ กฎนั้นจะใช้ไม่ได้หาก C ++ อนุญาตให้มีการกำหนดเอนทิตีในคลาสที่จำเป็นต้องเก็บไว้ในหน่วยความจำเป็นวัตถุ
เหตุใดstatic const
ประเภทอินทิกรัลและ enums เท่านั้นที่อนุญาตการเริ่มต้นในคลาส
คำตอบซ่อนอยู่ในคำพูดของ Bjarne อ่านอย่างใกล้ชิดว่า
"C ++ ต้องการให้ทุกวัตถุมีคำจำกัดความที่ไม่ซ้ำกันกฎนั้นจะใช้ไม่ได้หาก C ++ อนุญาตให้มีการกำหนดเอนทิตีในคลาสที่จำเป็นต้องเก็บไว้ในหน่วยความจำเป็นวัตถุ"
โปรดทราบว่าเฉพาะstatic const
จำนวนเต็มเท่านั้นที่สามารถถือว่าเป็นค่าคงที่ของเวลาในการคอมไพล์ คอมไพเลอร์รู้ว่าค่าจำนวนเต็มจะไม่เปลี่ยนแปลงตลอดเวลาและด้วยเหตุนี้จึงสามารถใช้เวทย์มนตร์ของตัวเองและใช้การปรับให้เหมาะสมได้คอมไพเลอร์จะแทรกสมาชิกคลาสดังกล่าวไว้เท่านั้นเช่นพวกเขาจะไม่ถูกเก็บไว้ในหน่วยความจำอีกต่อไปเนื่องจากความจำเป็นในการจัดเก็บในหน่วยความจำจะถูกลบออก มันทำให้ตัวแปรดังกล่าวยกเว้นกฎที่ Bjarne กล่าวถึง
เป็นที่น่าสังเกตว่าแม้ว่าstatic const
ค่าอินทิกรัลสามารถมีการเริ่มต้นในคลาสได้ แต่ก็ไม่อนุญาตให้ระบุที่อยู่ของตัวแปรดังกล่าว เราสามารถรับที่อยู่ของสมาชิกแบบคงที่ได้ถ้า (และเฉพาะในกรณีที่) มีคำจำกัดความที่ไม่อยู่ในคลาสสิ่งนี้จะตรวจสอบเหตุผลข้างต้นเพิ่มเติม
enums ได้รับอนุญาตเนื่องจากสามารถใช้ค่าของชนิดที่แจกแจงได้ในกรณีที่คาดว่า ints ดูการอ้างอิงด้านบน
สิ่งนี้เปลี่ยนแปลงอย่างไรใน C ++ 11?
C ++ 11 ผ่อนคลายข้อ จำกัด ในระดับหนึ่ง
C ++ 11 9.4.2 สมาชิกข้อมูลคงที่
§3
ถ้าสมาชิกข้อมูลแบบคงที่เป็นชนิด const literal การประกาศในนิยามคลาสสามารถระบุbrace-or-equal-initializerซึ่งทุกinitializer-clauseที่เป็นนิพจน์ที่กำหนดเป็นนิพจน์คงที่ สมาชิกข้อมูลแบบคงที่ของประเภทตัวอักษรสามารถประกาศได้ในนิยามคลาสด้วยconstexpr specifier;
ถ้าเป็นเช่นนั้นการประกาศจะต้องระบุตัวเริ่มต้นแบบรั้งหรือเท่ากันซึ่งทุกตัวเริ่มต้น - ประโยคที่เป็นนิพจน์การกำหนดคือนิพจน์คงที่ [หมายเหตุ: ในทั้งสองกรณีนี้สมาชิกอาจปรากฏในนิพจน์คงที่ —end หมายเหตุ] สมาชิกจะยังคงถูกกำหนดในขอบเขตเนมสเปซหากใช้ในโปรแกรมและข้อกำหนดขอบเขตเนมสเปซจะต้องไม่มีตัวเริ่มต้น
นอกจากนี้ C ++ 11 จะอนุญาตให้ (§12.6.2.8) สมาชิกข้อมูลที่ไม่คงที่สามารถเริ่มต้นได้เมื่อมีการประกาศ (ในคลาส) ซึ่งจะหมายถึงความหมายของผู้ใช้ที่ง่ายมาก
โปรดทราบว่าคุณลักษณะเหล่านี้ยังไม่ได้ใช้ใน gcc 4.7 ล่าสุดดังนั้นคุณอาจยังคงได้รับข้อผิดพลาดในการคอมไพล์