Question

Le code suivant lance std :: bad_cast

struct Foo {
    void foo () {}
};

struct Bar {
    Bar () {
        dynamic_cast <Foo &> (*this) .foo ();
    }
    virtual ~ Bar () {}
};

struct Baz : public Foo, public Bar {
};

int main ()
{
    Baz b;
}

Je me souviens une fois la lecture de la façon dont dynamic_cast a les compromis de performance de mise en œuvre, car « il traverse le réseau complet inheritence » afin d'évaluer correctement. Ce que les besoins du compilateur à faire ici est d'abord jeté et puis vers le bas.

Est-il possible de faire le travail ci-dessus ou dois-je ajouter virtual Foo* Bar::as_foo()=0; ?

Était-ce utile?

La solution

Il n'y a pas de fonctions virtuelles dans Foo, si dynamic_cast est parfaitement tenu à l'échec. Il doit y avoir une fonction virtuelle. Il est aussi une mauvaise idée de le faire lors de la construction, que vous allez rencontrer des problèmes d'ordre de construction.

Autres conseils

En supposant que Bar devrait hériter de Foo (ce qui ne fonctionne pas dans l'exemple actuel), le problème que vous voyez ici est généralement refered comme le problème diamant . Quelle version de foo ne souhaitez-vous utiliser, le Bar::foo() ou Foo::foo()? Vous allez avoir besoin de spécifier un héritage virtuel:

struct Foo{
    ~virtual Foo(){}
     void foo(){}
};

struct Bar : virtual public Foo

struct Baz : virtual public Foo, public Bar

pour faire savoir qu'il ne devrait exister un type de foo(). Par conséquent, héritage virtuel est utilisé pour invoquer l'appel à foo() dans le constructeur.

Edit:

Et pour être clair, je suppose que vous voulez Bar hériter de Foo. Si vous ne l'avez pas dans votre code, puis c'est la cause de la mauvaise erreur de casting. Il n'y a pas de hiérarchie d'héritage pour Bar à traverser pour se rendre à Foo. En outre, les compilateurs modernes ne devraient même pas compiler sans l'héritage virtuel, mais certains compilateurs anciens seront heureux @ # $ # $ vers le haut.

Et si je vais commenter une autre réponse, je suis mieux dans ma propre réponse!

Il y a quelques mauvaises choses dans votre exemple, peut-être que c'est un accident?

Bar n'a pas de Foo hérite, ne peut donc pas être jeté sur Foo dans le constructeur de Bar. Ils ne partagent pas également un parent d'héritage commun, et ne peuvent donc pas être jetés entre les uns des autres (sur le côté). Ce que vous voulez sans doute est:

struct withFoo {
    virtual void foo () {}
    virtual ~withFoo() {}
};

struct Foo : public virtual withFoo {
};

struct Bar : public virtual withFoo {
    Bar () {
        foo();  // no need to cast!
    }
};

struct Baz : public Foo, public Bar {
};

int main ()
{
    Baz b;
    b.foo(); // because of virtual inheritance from withFoo, there is no ambiguity here 
}

Hope this helps! Si vous avez besoin d'éclaircissements, s'il vous plaît demander!

La construction d'un Baz consiste à construire ses bases, et l'un d'entre eux est un bar. La base de la barre Baz ne peut être converti Foo, même si la finale Baz devrait être.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top