fonction virtuelle pure avec implémentation

ma compréhension de base est qu'il n'y a pas d'implémentation pour une fonction virtuelle pure, cependant, on m'a dit qu'il pourrait y avoir une implémentation pour la fonction virtuelle pure.

class A {
public:
    virtual void f() = 0;
};

void A::f() {
    cout<<"Test"<<endl;
}

est-ce que le code au-dessus est OK?

Quel est le but d'en faire une fonction purement virtuelle avec une implémentation?

145
demandé sur Eight 2010-01-18 23:45:42

8 réponses

une fonction pure virtual doit être implémentée dans un type dérivé qui sera instancié directement, cependant le type de base peut encore définir une implémentation. Une classe dérivée peut explicitement appeler l'implémentation de la classe de base (si les permissions d'accès le permettent) en utilisant un nom entièrement scopé (en appelant A::f() dans votre exemple-si A::f() était public ou protected ). Quelque chose comme:

class B : public A {

    virtual void f() {
        // class B doesn't have anything special to do for f()
        //  so we'll call A's

        // note that A's declaration of f() would have to be public 
        //  or protected to avoid a compile time problem

        A::f();
    }

};

le cas d'utilisation je peux penser de hors en haut de ma tête est quand il y a un comportement par défaut plus-ou-moins raisonnable, mais le concepteur de classe veut que le comportement de sorte-of-default soit invoqué seulement explicitement. Cela peut aussi être le cas ce que vous voulez que les classes dérivées exécutent toujours leur propre travail, mais aussi être en mesure d'appeler un ensemble commun de fonctionnalités.

notez que même si c'est permis par le langage, ce n'est pas quelque chose que je vois couramment utilisé (et le fait que cela puisse être fait semble surprendre la plupart des c++ programmeurs, même expérimentés).

180
répondu Michael Burr 2015-12-18 18:49:02

pour être clair, vous ne comprenez pas ce que = 0; après une fonction virtuelle signifie.

= 0 signifie que les classes dérivées doivent fournir une implémentation, non pas que la classe de base ne peut pas fournir une implémentation.

dans la pratique, quand vous marquez une fonction virtuelle comme pure (=0), Il y a très peu d'intérêt à fournir une définition, parce qu'elle ne sera jamais appelée à moins que quelqu'un ne le fasse explicitement via Base::Function(...) ou si le constructeur de classe de Base appelle la fonction virtuelle en question.

62
répondu Terry Mahaffey 2010-01-18 21:55:27

l'avantage est qu'il force les types dérivés à surpasser encore la méthode mais fournit également une implémentation par défaut ou additive.

20
répondu JaredPar 2010-01-18 20:49:31

si vous avez du code qui devrait être exécuté par la classe dérivante, mais vous ne voulez pas qu'il soit exécuté directement -- et vous voulez le forcer à être annulé.

votre code est correct, bien que tout cela ne soit pas une fonctionnalité souvent utilisée, et n'est généralement vu qu'en essayant de définir un destructeur virtuel pur -- dans ce cas, vous doit fournir une implémentation. La chose drôle est qu'une fois que vous dérivez de cette classe vous n'avez pas besoin de remplacer le destructeur.

par conséquent, la seule utilisation sensée des fonctions virtuelles pures est de spécifier un destructeur virtuel pur comme mot-clé" non-final".

le code suivant est étonnamment correct:

class Base {
public:
  virtual ~Base() = 0;
};

Base::~Base() {}

class Derived : public Base {};

int main() { 
  // Base b; -- compile error
  Derived d; 
}
16
répondu Kornel Kisielewicz 2010-01-18 21:22:00

il faudrait donner un corps à un destructeur virtuel pur, par exemple:)

Lire: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor /

(Lien brisé, archives)

5
répondu rmn 2017-09-20 14:27:42

Oui c'est correct. Dans votre exemple, les classes qui dérivent de A héritent à la fois de l'interface f() et d'une implémentation par défaut. Mais vous forcez les classes dérivées à implémenter la méthode f() (même si c'est seulement pour appeler l'implémentation par défaut fournie par A).

Scott Meyers en parle dans Effective C++ (2nd Edition) Item #36 Différenciate between inheritance of interface and inheritance of implementation. Le numéro de l'élément peut ont changé dans la dernière édition.

4
répondu Yukiko 2010-01-18 21:10:36

fonctions virtuelles pures avec ou sans un corps signifie simplement que les types dérivés doivent fournir leur propre mise en œuvre.

les corps de fonctions virtuelles pures dans la classe de base sont utiles si vos classes dérivées veulent appeler votre implémentation de classe de base.

4
répondu Brian R. Bondy 2010-04-09 18:12:42

la syntaxe' virtual void foo() =0; ' ne signifie pas que vous ne pouvez pas implémenter foo() dans la classe courante, vous pouvez. cela ne signifie pas non plus que vous devez l'implémenter dans les classes dérivées . Avant de me gifler, observons le problème du diamant.: (Code implicite, attention).

class A
{
public: 
    virtual void foo()=0;
    virtual void bar();
}

class B : public virtual A
{
public:
    void foo() { bar(); }
}

class C : public virtual A
{
public:
    void bar();
}

class D : public B, public C
{}

int main(int argc, const char* argv[])
{
    A* obj = new D();
    **obj->foo();**
    return 0;
}

maintenant, l'invocation obj->foo() résultera en B::foo () et puis C::bar ().

vous voyez... les méthodes virtuelles pures ne doivent pas être mises en œuvre dans les classes dérivées (foo () n'a pas d'implémentation dans la Classe C-compilateur compilera) En C++ il y a beaucoup de lacunes.

j'Espère que je pourrais aider :-)

1
répondu Nir Hedvat 2015-03-24 20:55:57