มันเป็นไปไม่ได้ แต่นั่นเป็นเพราะการละเลย ไม่ใช่สิ่งที่ "ไม่สมเหตุสมผล" เนื่องจากผู้คนจำนวนมากดูเหมือนจะอ้างสิทธิ์ เพื่อความชัดเจนฉันกำลังพูดถึงสิ่งนี้:
struct Base {
static virtual void sayMyName() {
cout << "Base\n";
}
};
struct Derived : public Base {
static void sayMyName() override {
cout << "Derived\n";
}
};
void foo(Base *b) {
b->sayMyName();
Derived::sayMyName(); // Also would work.
}
นี่คือบางสิ่งที่สามารถนำไปใช้งานได้100% (แต่ไม่ได้ใช้) และฉันจะเถียงกับบางสิ่งที่มีประโยชน์
พิจารณาว่าฟังก์ชั่นเสมือนปกติทำงานอย่างไร ลบstatic
s และเพิ่มสิ่งอื่น ๆ และเรามี:
struct Base {
virtual void sayMyName() {
cout << "Base\n";
}
virtual void foo() {
}
int somedata;
};
struct Derived : public Base {
void sayMyName() override {
cout << "Derived\n";
}
};
void foo(Base *b) {
b->sayMyName();
}
สิ่งนี้ทำงานได้ดีและสิ่งที่เกิดขึ้นคือคอมไพเลอร์สร้างสองตารางเรียกว่า VTables และกำหนดดัชนีให้กับฟังก์ชันเสมือนเช่นนี้
enum Base_Virtual_Functions {
sayMyName = 0;
foo = 1;
};
using VTable = void*[];
const VTable Base_VTable = {
&Base::sayMyName,
&Base::foo
};
const VTable Derived_VTable = {
&Derived::sayMyName,
&Base::foo
};
ถัดไปแต่ละคลาสที่มีฟังก์ชั่นเสมือนจริงจะถูกเพิ่มด้วยฟิลด์อื่นที่ชี้ไปที่ VTable ดังนั้นคอมไพเลอร์จะเปลี่ยนพวกเขาเป็นดังนี้
struct Base {
VTable* vtable;
virtual void sayMyName() {
cout << "Base\n";
}
virtual void foo() {
}
int somedata;
};
struct Derived : public Base {
VTable* vtable;
void sayMyName() override {
cout << "Derived\n";
}
};
แล้วสิ่งที่เกิดขึ้นจริงเมื่อคุณโทรb->sayMyName()
? โดยทั่วไปสิ่งนี้:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(พารามิเตอร์แรกกลายเป็นthis
)
โอเคแล้วมันจะทำงานกับฟังก์ชั่นเสมือนจริงได้อย่างไร? ความแตกต่างระหว่างฟังก์ชั่นสมาชิกแบบคงที่และไม่คงที่คืออะไร? ข้อแตกต่างคือหลังได้รับthis
ตัวชี้
เราสามารถทำสิ่งเดียวกันกับฟังก์ชันเสมือนแบบสแตติก - เพียงแค่ลบthis
ตัวชี้
b->vtable[Base_Virtual_Functions::sayMyName]();
สิ่งนี้สามารถรองรับไวยากรณ์ทั้งสอง:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
ดังนั้นอย่าเพิกเฉยต่อบรรดาผู้มีอิทธิพล มันไม่เข้าท่า ทำไมจึงไม่รองรับ ฉันคิดว่าเป็นเพราะมีประโยชน์น้อยมากและอาจทำให้สับสนเล็กน้อย
ข้อได้เปรียบทางเทคนิคเพียงอย่างเดียวของฟังก์ชั่นเสมือนปกติคือคุณไม่จำเป็นต้องผ่านthis
ไปยังฟังก์ชั่น แต่ฉันไม่คิดว่ามันจะสร้างความแตกต่างที่วัดได้ให้กับประสิทธิภาพ
หมายความว่าคุณไม่มีฟังก์ชั่นคงที่และไม่คงที่แยกกันสำหรับกรณีที่คุณมีอินสแตนซ์และเมื่อคุณไม่มีอินสแตนซ์ แต่ก็อาจสับสนว่าเป็นเพียง "เสมือน" จริง ๆ เมื่อคุณใช้ การเรียกอินสแตนซ์
const
ในลายเซ็นวิธีการตั้งค่าสถานะthis
ตัวชี้นัยเป็นค่าคงที่และไม่สามารถนำไปใช้กับวิธีการคงที่เมื่อพวกเขาขาดพารามิเตอร์โดยนัย