Qualcuno potrebbe aiutarmi a capire questo comportamento? Per essere corti:Comportamento strano durante l'estrazione di un'interfaccia nota da un contenitore polimorfico
- Ho memorizzato oggetti polimorfici in un contenitore comune.
- Alcuni di essi implementano un'interfaccia specifica. Posso dire quali.
- Ma non posso usare questa interfaccia.
Ecco quello che ho boilt giù a:
#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 -_-
}
Qualcuno può dirmi che cosa manco qui?
Fatto interessante: Se scambiare le definizioni di Base::~Base
e Base::describe
, quindi l'oggetto stesso descrive invece di essere distrutto. Come mai l'ordine conta nelle dichiarazioni dei metodi?
Fuori interesse, 'Interface * j = statico_cast (v [1]);' sembra funzionare, è sicuro? –
@ChrisDrew Finché tu * sai * che '* v [1]' è in realtà un'istanza di 'Derived' (o una classe derivata da quello), è sicuro. – Angew
@ChrisDrew Sì, va bene perché si sa che è un derivato *, quindi il 'static_cast' è OK. E poi il puntatore al derivato ('Derived *') al puntatore-base ('Interface *') è una conversione standard, quella è sempre OK. 'dynamic_cast' è più sicuro (ma più lento) perché se' v [1] 'non fosse un' Derived * ', otterresti un risultato ben definito (un puntatore nullo) invece di un puntatore dall'aspetto valido che produce un comportamento indefinito se lo usi – Barry