การเพิ่มประสิทธิภาพฐานที่ว่างเปล่าดีมาก อย่างไรก็ตามมันมาพร้อมกับข้อ จำกัด ดังต่อไปนี้:
การเพิ่มประสิทธิภาพฐานว่างเปล่าเป็นสิ่งต้องห้ามหากหนึ่งในคลาสฐานที่ว่างเปล่าเป็นชนิดหรือฐานของประเภทของข้อมูลสมาชิกไม่คงที่ครั้งแรกเนื่องจาก subobjects ฐานสองประเภทเดียวกันจะต้องมีที่อยู่ที่แตกต่างกันภายในการแสดงวัตถุ ประเภทที่ได้รับมากที่สุด
เพื่ออธิบายข้อ จำกัด นี้ให้พิจารณารหัสต่อไปนี้ static_assert
จะล้มเหลว ในขณะที่การเปลี่ยนแปลงอย่างใดอย่างหนึ่งFoo
หรือBar
เพื่อสืบทอดจากBase2
จะเป็นการหลีกเลี่ยงข้อผิดพลาด:
#include <cstddef>
struct Base {};
struct Base2 {};
struct Foo : Base {};
struct Bar : Base {
Foo foo;
};
static_assert(offsetof(Bar,foo)==0,"Error!");
ฉันเข้าใจพฤติกรรมนี้อย่างสมบูรณ์ สิ่งที่ฉันไม่เข้าใจคือสาเหตุพฤติกรรมนี้โดยเฉพาะอย่างยิ่งที่มีอยู่ เห็นได้ชัดว่ามีการเพิ่มเข้ามาด้วยเหตุผลเนื่องจากเป็นการเพิ่มที่ชัดเจนไม่ใช่การกำกับดูแล เหตุผลนี้คืออะไร
โดยเฉพาะอย่างยิ่งทำไม subobjects ทั้งสองควรจะต้องมีที่อยู่ที่แตกต่างกัน? ในข้างต้นBar
เป็นประเภทและfoo
เป็นตัวแปรสมาชิกประเภทนั้น ฉันไม่เห็นว่าทำไมชั้นฐานของBar
เรื่องถึงชั้นฐานของประเภทfoo
หรือในทางกลับกัน
อันที่จริงฉันมีอะไรถ้าฉันคาดหวังว่า&foo
จะเป็นเช่นเดียวกับที่อยู่ของBar
อินสแตนซ์ที่มีมัน - มันจะต้องอยู่ในสถานการณ์อื่น(1) (1)หลังจากทั้งหมดฉันไม่ได้ทำอะไรแฟนซีกับการvirtual
สืบทอดคลาสพื้นฐานว่างเปล่าโดยไม่คำนึงถึงและการคอมไพล์ด้วยBase2
แสดงว่าไม่มีอะไรแตกในกรณีนี้โดยเฉพาะ
แต่ชัดเจนว่าเหตุผลนี้ไม่ถูกต้องอย่างใดอย่างหนึ่งและมีสถานการณ์อื่น ๆ ที่จะต้องมีข้อ จำกัด นี้
สมมติว่าคำตอบควรเป็น C ++ 11 หรือใหม่กว่า (ขณะนี้ฉันใช้ C ++ 17)
(1)หมายเหตุ: EBO ได้รับการอัพเกรดใน C ++ 11 และโดยเฉพาะอย่างยิ่งกลายเป็นข้อบังคับสำหรับStandardLayoutType
s (แม้ว่าBar
เหนือไม่ใช่ไม่ใช่StandardLayoutType
)
Base *a = new Bar(); Base *b = a->foo;
มีa==b
แต่a
และb
เห็นได้ชัดว่าวัตถุที่แตกต่าง (อาจจะมีการแทนที่วิธีการเสมือนแตกต่างกัน)