สมมติว่าฉันมีคลาสนามธรรมที่มีราคาแพงในการสร้างและคัดลอก:
class AbstractBase {
public:
AbstractBase() {
for (int i = 0; i < 50000000; ++i) {
values.push_back(i);
}
}
virtual void doThing() = 0;
private:
vector<int> values;
};
มันมีสองคลาสย่อย FirstDerived
:
class FirstDerived : public AbstractBase {
public:
void doThing() {
std::cout << "I did the thing in FirstDerived!\n";
}
};
และ SecondDerived
:
class SecondDerived : public AbstractBase {
public:
void doThing() {
std::cout << "I did the thing in SecondDerived!\n";
}
};
นอกจากนี้ ฉันต้องการสร้างคลาสที่ใช้ FirstDerived
หรือ SecondDerived
โดยใช้การเรียบเรียง (ไม่ใช่การรวมกลุ่ม) หมายความว่าฉันต้องการ ComposedOfAbstractBase
เป็นเจ้าของ ไม่ว่าจะส่งผ่านชั่วคราวใดก็ตาม หากฉันไม่ได้ใช้คลาสนามธรรมในคลาสนี้จะมีลักษณะดังนี้: (ใน C ++ 11)
class ComposedOfWhicheverDerived {
public:
ComposedOfWhicheverDerived(AbstractBase abstract_base) : abstract_base(std::move(abstract_base)) {;}
private:
AbstractBase abstract_base;
};
อย่างไรก็ตาม สิ่งนี้ใช้ไม่ได้กับคลาสนามธรรมเนื่องจากฉันไม่สามารถสร้างอินสแตนซ์ของ AbstractBase
ได้ แม้ว่าฉันจะระมัดระวังที่จะไม่ส่งผ่าน AbstractBase
ชั่วคราวก็ตาม เช่น:
ComposedOfWhicheverDerived a(FirstDerived());
สำหรับคอมไพเลอร์สิ่งนี้แย่พอ ๆ กับ:
ComposedOfWhicheverDerived b(AbstractBase());
เพราะฉันยังมีอินสแตนซ์ AbstractBase
ในการประกาศคลาส
วิธีแก้ปัญหาต่อไปที่ฉันคิดคือ:
class ComposedOfAbstractBase {
public:
ComposedOfAbstractBase(AbstractBase&& abstract_base) : some_derived_instance(abstract_base) {;}
private:
AbstractBase& some_derived_instance;
};
มันใช้งานได้อย่างสมบูรณ์แบบ (แม้ว่าฉันจะไม่เข้าใจมันก็ตาม)! ทั้งสองกรณีนี้ถูกต้องและทำงานตามที่ตั้งใจไว้:
ComposedOfAbstractBase a(FirstDerived());
ComposedOfAbstractBase b(SecondDerived());
จะไม่สร้างสำเนาของอะไรก็ตามที่ส่งผ่าน AbstractBase
ชั่วคราว และอนุญาตให้จัดเก็บการอ้างอิงถึง AbstractBase
ได้ แม้ว่าอย่างดีที่สุดแล้ว การอ้างอิงถึงการอ้างอิงค่า r ดูเหมือนจะไม่ชัดเจน แต่ก็ไม่ได้หมายความว่า ComposedOfAbstractBase
เป็นเจ้าของ ไม่ว่าค่าใดจะถูกส่งผ่านแบบชั่วคราว นอกจากนั้น ปรากฎว่าโซลูชันนี้ดูเหมือนว่าจะมีประสิทธิภาพไม่ดีนัก เพื่อแสดงสิ่งนี้ฉันจึงสร้างคลาสนี้:
class ComposedOfFirstDerived {
public:
ComposedOfFirstDerived(FirstDerived first_derived) : first_derived(std::move(first_derived)) {;}
private:
FirstDerived first_derived;
};
ซึ่งสามารถรับได้เฉพาะใน FirstDerived
เท่านั้น ดังนั้นเราจึงสามารถใช้ std::move
เพื่อลดภาระการเป็นเจ้าของชั่วคราวได้ ฉันสามารถสร้างตัวอย่างดังนี้:
ComposedOfFirstDerived c(FirstDerived());
สิ่งที่น่าสนใจคือคลาสนี้สร้างได้เร็วกว่า ComposedOfAbstractClass
ถึง 10% อย่างสม่ำเสมอ
ไม่มีใครรู้ว่าเกิดอะไรขึ้นที่นี่? เหตุใด ComposedOfFirstDerived
จึงสร้างได้เร็วกว่า ComposedOfAbstractBase
มาก มีวิธีที่ดีกว่าในการจัดองค์ประกอบด้วยคลาสนามธรรมหรือฉันติดอยู่กับวิธีแก้ปัญหาที่ไม่เหมาะสมหรือไม่?
ขออภัยถ้านี่เป็นคำถามที่ปากมาก ฉันขอขอบคุณทุกคนที่สละเวลาอ่านและให้คำตอบอย่างแท้จริง เพราะฉันนิ่งงันมาก!