Hãy xem xét tình huống này rất đơn giản:C++ chức năng ảo không được gọi trong lớp con
A.h
class A {
public:
virtual void a() = 0;
};
B.h
#include <iostream>
class B {
public:
virtual void b() {std::cout << "b()." << std::endl;};
};
C.h
#include "A.h"
#include "B.h"
class C : public B, public A {
public:
void a() {std::cout << "a() in C." << std::endl;};
};
int main() {
B* b = new C();
((A*) b)->a(); // Output: b().
A* a = new C();
a->a(); // Output:: a() in C.
return 0;
}
Nói cách khác:
- A là một lớp ảo tinh khiết .
- B là một lớp không có siêu lớp và một hàm ảo không thuần túy.
- C là một phân lớp của A và B và ghi đè chức năng ảo thuần túy của A.
gì làm tôi ngạc nhiên là sản phẩm đầu tiên ví dụ:
((A*) b)->a(); // Output: b().
Mặc dù tôi gọi một() trong mã, b() được gọi. Tôi đoán là nó liên quan đến thực tế là biến b là một con trỏ đến lớp B mà không phải là một lớp con của lớp A. Nhưng vẫn là kiểu thời gian chạy là một con trỏ tới một cá thể C.
Quy tắc C++ chính xác để giải thích điều này, từ quan điểm Java, hành vi kỳ lạ là gì?
Đặt đơn giản là: ** B không phải là A! ** Chúng hoàn toàn không liên quan với nhau, nhưng của bạn (không tốt để sử dụng!) C-phong cách diễn viên không quan tâm một trong hai cách. 'dynamic_cast' sẽ duyệt chính xác hệ thống phân cấp của bạn. Khi bạn truyền các loại con trỏ không liên quan, bạn sẽ nhận được hành vi không xác định. Điều đó có nghĩa là bất cứ điều gì có thể xảy ra, từ nó dường như làm việc để thổi máy tính của bạn lên. – GManNickG
Đừng quên những con quỷ mũi. –