Vâng, bạn có thể làm điều gì đó tương tự bằng cách sử dụng một số thủ thuật với ghi đè giá trị this
. Bạn có lẽ không bao giờ nên cố gắng làm điều đó mặc dù, vtable
con trỏ không có nghĩa là phải được sửa đổi bằng tay.
Để làm những gì bạn mô tả, chúng tôi cần phải có con trỏ đến A vtable
. Đối tượng của chúng tôi p
chỉ trỏ đến số vtable
của B, vì vậy chúng tôi cần lưu trữ con trỏ thứ hai trong một trường trong hàm tạo của A.
Đây là mã:
#include <iostream>
struct A{
virtual void foo() { std::cout << "A::foo()" << std::endl; }
int *a_vtable_ptr;
// First, save value of A's vtable pointer in a separate variable.
A() { a_vtable_ptr = *(int**)this; }
};
struct B:A{
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void callBase(void (A::*f)()){
int *my_vtable_ptr = *(int**)this;
// Then modify vtable pointer of given object to one that corresponds to class A.
*(int**)this = a_vtable_ptr;
(this->*f)(); // Call the method as usual.
// Restore the original vtable pointer.
*(int**)this = my_vtable_ptr;
}
};
// Function main() is not modified.
int main(){
B* p=new B();
void (A::*f)() = &A::foo;
p->callBase(f);
}
Output:
A::foo()
Process finished with exit code 0
Tôi không nghĩ rằng bạn có thể. Tuy nhiên, tôi đã sai trong quá khứ :) Hãy hy vọng một người hiểu biết nhiều hơn tôi biết một cách. –
Bạn có thể gọi nó trực tiếp như 'p-> A :: foo();' nhưng không thông qua con trỏ tới hàm thành viên (mà tôi đoán là điểm của các hàm ảo). –
Tôi tin rằng bạn làm việc xung quanh điều này bằng cách có một 'bar' không ảo thực hiện công việc và có' foo' delegate tới 'bar',' callBase' sau đó gọi 'bar'. Điều này là hợp lý hơn vì đa hình có nghĩa là 'B' nên luôn luôn gọi riêng' foo' –