ยังไม่ชัดเจนว่าคุณหมายถึงอะไรโดย "สืบทอดตัวสร้างหลัก" คุณใช้คำว่าเอาชนะซึ่งแสดงให้เห็นคุณอาจจะคิดเกี่ยวกับการก่อสร้างที่ประพฤติเช่นฟังก์ชั่นเสมือน polymorphic ฉันจงใจไม่ใช้คำว่า "virtual constructors" เพราะนั่นเป็นชื่อสามัญสำหรับรูปแบบโค้ดที่คุณต้องการอินสแตนซ์ที่มีอยู่แล้วของวัตถุเพื่อสร้างอีกอันหนึ่ง
มียูทิลิตีเพียงเล็กน้อยสำหรับตัวสร้าง polymorphic นอกรูปแบบ "ตัวสร้างเสมือน" และมันยากที่จะเกิดขึ้นกับสถานการณ์ที่เป็นรูปธรรมซึ่งอาจมีการใช้ตัวสร้างแบบ polymorphic จริง ตัวอย่างที่มีการวางแผนไว้อย่างมากซึ่งไม่สามารถใช้งานได้จาก C ++ ในระยะไกล :
struct Base {
virtual Base(unsigned p1, unsigned p2) {...}
};
struct Derived: public Base {
Derived(unsigned p1, unsigned p2) : Base(p1, p2) override {...}
};
int main(void) {
unsigned p1 = 0;
unsigned p2 = 42;
Derived *p_d1 = new Base(p1, p2); // This might call Derived(unsigned, unsigned).
Derived *p_d2 = nullptr;
p_d2 = new Base(p1, p2); // This might call Derived(unsigned, unsigned) too.
}
ในกรณีนี้คอนสตรัคเตอร์ที่เรียกว่าขึ้นอยู่กับชนิดคอนกรีตของตัวแปรที่ถูกสร้างหรือกำหนด มันมีความซับซ้อนในการตรวจจับในระหว่างการแยกวิเคราะห์ / การสร้างรหัสและไม่มีประโยชน์: คุณรู้ประเภทคอนกรีตที่คุณกำลังสร้างและคุณได้เขียนนวกรรมิกเฉพาะสำหรับคลาสที่ได้รับ รหัส C ++ ที่ถูกต้องต่อไปนี้จะเหมือนกันทุกประการสั้นกว่าเล็กน้อยและชัดเจนยิ่งขึ้นในสิ่งที่ทำ:
struct Base {
Base(unsigned p1, unsigned p2) {...}
};
struct Derived: public Base {
Derived(unsigned p1, unsigned p2) : Base(p1, p2) {...}
};
int main(void) {
unsigned p1 = 0;
unsigned p2 = 42;
Derived *p_d1 = new Derived(p1, p2);
Derived *p_d2 = nullptr;
p_d2 = new Derived(p1, p2);
}
การตีความครั้งที่สองหรือคำถามเพิ่มเติมคือ - จะเกิดอะไรขึ้นถ้าตัวสร้างคลาสฐานปรากฏขึ้นโดยอัตโนมัติในคลาสที่ได้รับทั้งหมดเว้นแต่จะซ่อนไว้อย่างชัดเจน
หากเด็กได้สืบทอดคอนสตรัคเตอร์หลักสิ่งที่สามารถผิดพลาดได้?
คุณจะต้องเขียนรหัสเพิ่มเติมเพื่อซ่อนตัวสร้างหลักที่ไม่ถูกต้องที่จะใช้ในการสร้างคลาสที่ได้รับ สิ่งนี้สามารถเกิดขึ้นได้เมื่อคลาสที่ได้รับนั้นเชี่ยวชาญคลาสพื้นฐานในวิธีที่พารามิเตอร์บางตัวไม่เกี่ยวข้อง
ตัวอย่างทั่วไปคือสี่เหลี่ยมและสี่เหลี่ยม (โปรดสังเกตว่าสี่เหลี่ยมและสี่เหลี่ยมโดยทั่วไปไม่ใช่ Liskov-substituted ดังนั้นจึงไม่ใช่การออกแบบที่ดีมาก แต่เน้นให้เห็นถึงปัญหา)
struct Rectangle {
Rectangle(unsigned width, unsigned height) {...}
};
struct Square : public Rectangle {
explicit Square(unsigned side) : Rectangle(side, side) {...}
};
หาก Square ได้รับค่าคอนสตรัคเตอร์สองค่าของ Rectangle คุณสามารถสร้างสี่เหลี่ยมที่มีความสูงและความกว้างต่างกัน ... นั่นเป็นเหตุผลทางตรรกะดังนั้นคุณจึงต้องการซ่อนตัวสร้างนั้น