10
votes

Déterminer si une classe dérivée remplace une méthode d'une classe de base

class B {
virtual int foo();
};

class D : public B {
virtual int foo() { cout<<"D\n"; }
};

int B::foo()
{
   /* how do i tell if this->foo() is overridden by a subclass, or if it will */
   /* simply recurse into B::foo()? */
   this->foo();
}

main()
{
D d;
d.B::foo();
}

9 commentaires

Il n'y a probablement pas de manière fiable. Pourquoi voudriez-vous?


Je suis d'accord avec oli- juste appeler d.foo () comme une personne normale.


Je veux compléter ma réponse avec des points de vue personnels supplémentaires. Je fais de mon mieux pour ne jamais remettre en question pourquoi quelqu'un veut faire quelque chose. Je ne peux pas savoir pourquoi ils veulent faire quelque chose, tout ce que je sais, c'est qu'ils ont posé une question. Je pense que c'est bien d'essayer de résoudre leur problème et de fournir une alternative qu'ils ne pensaient pas, mais des déclarations comme "le faire comme une personne normale" ne sont ni constructives ni utiles.


@ADEWREW: J'aurais beaucoup écrit mon commentaire beaucoup plus, mais, eh bien, tu dois faire tant de personnages. En outre, comme quelqu'un qui est à l'autre bout de tels commentaires tout le temps et qui n'est certainement pas une personne normale, je me sens assez confiant en sachant que ces commentaires sont humorisés et quand ce n'est pas le cas.


@Deadmg texte brut est parfois si difficile de transmettre l'émotion et le contexte humoristique, alors je m'excuse. Nous devrions embrasser. :) Je pense que je viens de lire trop de questions récemment lorsque les gens critiquent leurs raisons de faire quelque chose. Si nous sommes sur ce site Web, je dirais que ça ne va pas d'entre nous, n'est normal. :)


Il est inutile de se demander pourquoi je veux faire cela. Dire "appeler juste d.foo ()" est une réponse retardée. Je pourrais passer une heure à expliquer pourquoi cela serait utile dans ma situation, et cela vous permettrait de citer des moyens d'accomplir ce que je veux d'une autre manière. Mais je sais déjà comment accomplir ce que je veux par ingénierie autour de cette limitation de C ++. Donc, il n'est pas nécessaire de gaspiller le temps de tout le monde avec un boutier de bavardage.


Il est trop tard pour rétracter mon commentaire de défense basé sur son utilisation du mot "retardé" :) Je suppose que mon problème principal est que, j'ai un effet difficile d'accepter "il ne peut pas être fait" voir autant que ce soit autant peut être fait, Et vous pouvez écrire votre propre RTTI en C ++ si nécessaire. La vraie réponse est que cela peut être fait, mais cela compliquera votre code au point qu'il est préférable de faire autre chose.


Je n'accepterais pas que ceci est une limitation de C ++. Ce que vous essayez de faire réellement gère le comptoir à peu près à chaque plaidoyer pour raisonner qui existe. Bien et bien étant curieux si cela peut être fait, mais qu'il ne faut pas vous guider pour conclure que la langue est "limitée". Je ne peux pas penser à un dans lequel une telle construction serait possible.


lol je ne pense pas que c ++ est une langue limitée, un mauvais choix de mots de ma part. Ironique parce que, en fait, je pense que c ++ est une langue trop large. Mais c'est un débat un autre.


5 Réponses :


8
votes

réponse: vous ne pouvez pas.

J'y développerais s'il y avait quelque chose à se développer.


0 commentaires

0
votes

La manière la plus sûre consiste à ne pas remplacer FOO (), mais permettez de remplacer une fonction Onfoo () qui s'appelle à partir de la base de base si vous ne pouvez pas faire confiance à vos programmeurs. MFC fait beaucoup de celles-ci pour assurer un comportement par défaut (plutôt que de protéger contre la recurision).

Ensuite, également à un niveau statique, tout ce qui implémente Onfoo () est facilement repéré avec une "recherche dans des fichiers".

E.g. (non testé pour la syntaxe / compilation et non threadsafe) xxx


0 commentaires

1
votes

Je déteste même à fournir cela .. mais ici, il est xxx pré>

edit strong> p>

Je veux prouver que cela fonctionne dans MSVC ++ 2010 . p> xxx pré>

sortie em> p>

class D : public B { };


2 commentaires

Cela ne fonctionne pas. Il ne dit pas si FOO () est remplacé et, en fait, si ce n'est pas votre code recueille infiniment sur un appel à FOO () sur un objet D; exactement ce que l'OP veut éviter. En fait, cela ne vous aide pas à trouver quoi que ce soit au-delà de la question de savoir si le B FOO () est appelé est en fait une version plus spécifiée ou non ... c'est tout. Les points seraient plus significatifs si les gens ne leur laissaient pas de les remettre avant de vérifier la validité de la réponse.


@ Noah Roberts Vous êtes correct, si D ne remplace pas B :: FOO Cela recueille. Cela peut également être résolu en utilisant la pile déroulant. Créez une variable sur la pile qui définit un drapeau dans le stockage local de fil une fois entré dans B :: FOO (), si B: FOO () est revenu à nouveau via la même pile et tente de créer une autre variable, elle peut vérifier si Le drapeau a été défini puis quitter. Une fois la pile déroulant la destruction de la variable peut non définir le drapeau. Ma solution résout le problème exact qu'il a donné, qui est ma faute car je n'ai pas lu dans d'autres scénarios qui auraient pu survenir.



2
votes

Une approche est de faire foo () code> fonction virtuelle pure em> in B code>, et strong> le définissez également. De cette façon, vous vous assurez que les classes dérivées de B code> doivent forts> définir foo () code>. Voici B,

class B
{
public:
        virtual int foo() = 0; //pure virtual function
};

//pure virtual function also has a default implementation!
int B::foo()
{
        std::cout << "B" << std::endl;  
        this->foo(); //this will call the overridden foo() in the derived class!
        return 0;
}


2 commentaires

Cela le rend afin qu'il ne puisse pas instancer une instance de B. Nous ne savons pas s'il souhaite toujours créer des objets de type B.


Oui, bien sûr, je me rends compte qu'il y a un tas de moyens d'ingénieur autour de cela, mais ma question est de savoir s'il y a une manière construite à la RTTI C ++ pour faire ce que je veux.



0
votes

Comme d'autres ont souligné, il n'y a pas de moyen fiable de le faire. Je vous exhorte à repenser votre conception ...


1 commentaires

Eh bien, oui, ce serait bien si je pouvais redessiner le code maladroit du développeur précédent, mais il n'y a pas de cartes non dans les cartes en ce moment.