Giả sử tôi có một kiểu con trỏ có thể chứa địa chỉ của một phương thức lớp cơ sở. Tôi có thể gán địa chỉ của một phương thức phân lớp cho nó và mong nó hoạt động chính xác không? Trong trường hợp của tôi, tôi đang sử dụng nó với một con trỏ lớp cơ sở và kiểu động của đối tượng là lớp dẫn xuất.Có an toàn để "upcast" một con trỏ phương pháp và sử dụng nó với con trỏ lớp cơ sở?
struct B
{
typedef void (B::*MethodPtr)();
};
struct D: public B
{
void foo() { cout<<"foo"<<endl; }
};
int main(int argc, char* argv[])
{
D d;
B* pb = &d;
//is the following ok, or undefined behavior?
B::MethodPtr mp = static_cast<B::MethodPtr>(&D::foo);
(pb->*mp)();
}
Tiêu chuẩn nói điều này khi nói về static_cast:
5.2.9.9 Một rvalue kiểu “con trỏ tới thành viên của D loại CV1 T” có thể được chuyển đổi sang một rvalue kiểu “con trỏ thành phần B của loại cv2 T ”, trong đó B là một lớp cơ sở (điều 10) của D, nếu chuyển đổi chuẩn hợp lệ từ" con trỏ thành thành viên B loại T "thành" con trỏ thành thành viên D của kiểu T " tồn tại (4.11), và cv2 là cùng mức độ cv, hoặc bằng cv lớn hơn, cv1. 63) Giá trị con trỏ thành viên null (4.11) được chuyển thành giá trị con trỏ thành viên null của kiểu đích. Nếu lớp B chứa thành viên ban đầu, hoặc là một lớp cơ sở hoặc dẫn xuất của lớp có chứa thành viên ban đầu, thì con trỏ kết quả đến các thành viên trỏ đến thành viên ban đầu. Nếu không, kết quả của diễn viên là không xác định. [Lưu ý: mặc dù lớp B cần không chứa thành viên ban đầu, loại động của đối tượng mà con trỏ tới thành viên bị hủy đăng ký phải chứa thành viên ban đầu; xem 5.5.]
Như mọi khi, tôi có một thời gian khó giải mã tiêu chuẩn. Nó kinda nói rằng nó là ok, nhưng tôi không chắc chắn 100% nếu các văn bản trên thực sự áp dụng cho tình hình trong mã ví dụ của tôi.
tại sao bạn không thể sử dụng chức năng ghi đè chức năng ảo thông thường? – YeenFei
mã hóa hơi giống như đi bộ trên một con đường núi, đi bộ ở giữa đường là an toàn hơn so với đi bộ gần vành, mã của bạn dường như gần với vành. :-) –