Hãy xem xét đoạn mã sau:quá tải ảo chức năng cuộc gọi có độ phân giải
class Abase{};
class A1:public Abase{};
class A2:public A1{};
//etc
class Bbase{
public:
virtual void f(Abase* a);
virtual void f(A1* a);
virtual void f(A2* a);
};
class B1:public Bbase{
public:
void f(A1* a);
};
class B2:public Bbase{
public:
void f(A2* a);
};
int main(){
A1* a1=new A1();
A2* a2=new A2();
Bbase* b1=new B1();
Bbase* b2=new B2();
b1->f(a1); // calls B1::f(A1*), ok
b2->f(a2); // calls B2::f(A2*), ok
b2->f(a1); // calls Bbase::f(A1*), ok
b1->f(a2); // calls Bbase::f(A2*), no- want B1::f(A1*)!
}
Tôi muốn biết tại sao C++ chọn để giải quyết các cuộc gọi chức năng trên dòng cuối cùng bởi upcasting con trỏ this
của đối tượng vào cơ sở lớp học, thay vì upcasting các đối số của f()
? Có cách nào để tôi có thể có được hành vi mà tôi muốn không?
Cảm ơn - như tôi đã hiểu, vấn đề là độ phân giải mà lệnh gọi f() ảo xảy ra tại thời gian biên dịch, dựa trên đối số được cung cấp cho f(). Vì vậy, trên dòng cuối cùng, trình biên dịch đã quyết định rằng f (A2 *) sẽ được gọi. Phiên bản của f (A2 *) được gọi sau đó phụ thuộc vào loại thời gian chạy được trỏ đến. Ở đây, vì lớp B1 không vượt quá f (A2 *), nên phiên bản lớp cơ sở được gọi. – stw
@stw, hoàn toàn chính xác. –