Có ai giúp tôi hiểu hành vi này không? Để viết tắt:Hành vi lạ khi trích xuất giao diện đã biết từ thùng chứa đa hình
- Tôi đã lưu trữ các đối tượng đa hình trong một vùng chứa chung.
- Một số người trong số họ triển khai một giao diện cụ thể. Tôi có thể nói cái nào.
- Nhưng tôi không thể sử dụng giao diện này.
Dưới đây là những gì tôi đã boilt nó xuống:
#include <iostream>
#include <vector>
// A base class
struct Base {
// A polymorphic method
virtual void describe() const {
std::cout << "Base" << std::endl;
};
virtual ~Base(){
std::cout << " Base destroyed" << std::endl;
};
};
// A specific interface
struct Interface {
virtual ~Interface(){
std::cout << " Interface Destroyed" << std::endl;
};
virtual void specific() = 0;
};
// A derived class..
struct Derived : public Base, public Interface {
virtual void describe() const {
std::cout << "Derived" << std::endl;
};
virtual void specific() {
std::cout << "Derived uses Interface" << std::endl;
};
virtual ~Derived() {
std::cout << " Derived destroyed" << std::endl;
};
};
int main() {
// Test polymorphism:
Base* b(new Base());
Derived* d(new Derived());
b->describe(); // "Base"
d->describe(); // "Derived"
// Ok.
// Test interface:
d->specific(); // "Derived uses Interface"
Interface* i(d);
i->specific(); // "Derived uses Interface"
// Ok.
// Here is the situation: I have a container filled with polymorphic `Base`s
std::vector<Base*> v {b, d};
// I know that this one implements the `Interface`
Interface* j((Interface*) v[1]);
j->specific(); // " Derived destroyed"
// " Interface destroyed"
// " Base destroyed"
// Why?! What did that object do to deserve this?
return EXIT_SUCCESS; // almost -_-
}
bất cứ ai có thể cho tôi biết những gì tôi đang mất tích ở đó?
Thú vị thực tế: Nếu tôi hoán đổi các định nghĩa của Base::~Base
và Base::describe
, thì đối tượng mô tả chính nó thay vì bị hủy. Làm thế nào đến thứ tự các vấn đề trong khai báo phương pháp?
Không quan tâm, 'Giao diện * j = static_cast (v [1]);' cũng có vẻ hoạt động, có an toàn không? –
@ChrisDrew Miễn là bạn biết * rằng '* v [1]' thực sự là một thể hiện của 'Derived' (hoặc một lớp dẫn xuất từ đó), nó an toàn. – Angew
@ChrisDrew Có, điều đó tốt vì bạn biết đó là một 'Có nguồn gốc *', do đó, 'static_cast' là OK. Và sau đó con trỏ để xuất phát ('Derived *') đến con trỏ đến cơ sở ('Giao diện *') là một chuyển đổi tiêu chuẩn, mà một trong những luôn luôn là OK. 'dynamic_cast' là an toàn hơn (nhưng chậm hơn) vì nếu' v [1] 'không phải là' Derived * ', bạn sẽ nhận được kết quả được xác định rõ ràng (một con trỏ null) thay vì một con trỏ tìm kiếm hợp lệ mang lại hành vi không xác định nếu bạn sử dụng nó. – Barry