Question

Je l'apprentissage de C ++ dans une classe en ce moment et je n'assimilez pas tout à fait des fonctions virtuelles pures. Je comprends qu'ils sont décrits plus loin dans une classe dérivée, mais pourquoi voudriez-vous déclarer comme égale à 0 si vous allez juste définir dans la classe dérivée?

Était-ce utile?

La solution

En bref, il est de faire la classe abstraite, de sorte qu'il ne peut pas être instancié, mais une classe enfant peut remplacer les méthodes virtuelles pures pour former une classe concrète. Ceci est une bonne façon de définir une interface en C ++.

Autres conseils

Cela force une classe dérivée pour définir la fonction.

Toute classe contenant une méthode virtuelle pure sera abstraite, qui est, il ne peut pas être instancié. Les classes abstraites sont utiles pour définir un comportement de base qui sous-classes doivent partager, mais permettant (en fait, exigeant) pour mettre en œuvre des sous-classes individuellement l'abstrait.

Un exemple d'une classe abstraite:

class Foo {

    // pure virtual, must be implemented by subclasses
    virtual public void myMethod() = 0;

    // normal method, will be available to all subclasses,
    // but *can* be overridden
    virtual public void myOtherMethod();
};

Une classe dans laquelle chaque méthode est abstraite peut être utilisé comme une interface, exigeant que tous les sous-classes pour se conformer à l'interface en mettant en œuvre toutes les méthodes qu'il contient.

Un exemple d'une interface:

class Bar {

    // all method are pure virtual; subclasses must implement
    // all of them
    virtual public void myMethod() = 0;

    virtual public void myOtherMethod() = 0;
};

virtuelles pures en C ++ sont essentiellement une façon de définir des interfaces sans les obliger à mettre en œuvre.

Imaginez que je veux modéliser plusieurs sortes de formes, et tous ont une zone bien définie. Je décide que chaque forme doit hériter IShape ( "I" pour l'interface), et comprendra une GetArea() méthode <=>:

class IShape {
    virtual int GetArea();
};

Maintenant, le problème: comment dois-je calculer la surface d'une forme si cette forme ne l'emporte pas sur <=>? À savoir, quelle est la meilleure implémentation par défaut? Les cercles utilisent pi * rayon ^ 2, carrés utiliser la longueur ^ 2, et des parallélogrammes rectangles utilisent la base de la hauteur *, triangles utilisent hauteur 1/2 de base *, losanges, des pentagones, des octogones, etc. utiliser d'autres formules.

Je dis « si vous êtes une forme que vous devez définir une façon de calculer la zone, mais damné si je sais ce qui sera » en définissant la méthode virtuelle pure:

class IShape {
    virtual int GetArea() = 0;
};

Pour ajouter à la réponse de Steven Sudit:

"En bref, il est de faire la classe abstraite, de sorte qu'il ne peut pas être instancié, mais une classe enfant peut remplacer les méthodes virtuelles pures pour former une classe concrète. Ceci est une bonne façon de définir une interface en C ++. «

Un exemple de ceci serait si vous aviez une classe de base (forme peut-être) que vous utilisez pour définir un certain nombre de fonctions membres que ses classes dérivées peuvent utiliser, mais veulent éviter une instance de forme étant déclarée et les utilisateurs Forcez utiliser uniquement les classes dérivées (qui peut être, Rectangle, Triangle, Pentagone, et ainsi de suite)

RE: Réponse de Jeff ci-dessus

classes non abstraites peuvent contenir des fonctions membres virtuelles et être instancié. En fait, pour la surcharge des fonctions membres comme cela est requis par défaut C ++ ne détermine pas le type d'exécution d'une variable, mais lorsqu'elle est définie en utilisant mot-clé th virtuel, il sera.

Considérez ce code (note, accesseurs, mutators, constructeurs, etc. ne sont pas inclus dans un souci de clarté):

class Person{
  int age;

  public:
    virtual void print(){
      cout << age <<endl;
    }
}

class Student: public Person{
  int studentID

  public:
    void print(){
      cout << age << studentID <<endl;
    }
}

lors de l'exécution de ce code:

 Person p = new Student();
 p.print();

sans le mot-clé virtuelle, que l'âge serait imprimé, pas l'âge et idEtudiant comme il est censé se produire pour la classe des étudiants

(cet exemple est basé sur un de c ++ très similaire pour les programmeurs Java http: //www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X )

@Steven Sudit: vous êtes tout à fait correct, je négligé d'inclure l'héritage réel, doh! Le accesseurs etc ne sont pas inclus pour garder les choses plus claires, et je l'ai fait que plus évident maintenant. 07/03/09: tous les fixes

Essentiellement, virtuals purs sont utilisés pour créer une interface (similaire à Java). Cela peut être utilisé comme un accord entre deux modules (ou classes, ou autre) à quel genre de fonctionnalités à attendre, sans avoir à connaître quoi que ce soit au sujet de la mise en œuvre de l'autre pièce. Cela vous permet de brancher facilement et jouer des morceaux en utilisant la même interface sans avoir à changer quoi que ce soit dans l'autre module qui utilise l'interface.

Par exemple:

class IStudent
{
    public:
    virtual ~IStudent(){};
    virtual std::string getName() = 0;
};


class Student : public IStudent
{
    public:
    std::string name;
    std::string getName() { return name; };
    void setName(std::string in) { name = in; };
};

class School
{
    public:
    void sendStudentToDetention(IStudent *in) {
        cout << "The student sent to detention is: ";
        cout << in->getName() << endl;
    };
};

int main()
{
    Student student;
    student.setName("Dave");

    School school;
    school.sendStudentToDetention(&student);
return 0;
}

L'école n'a pas besoin de savoir comment définir le nom d'un étudiant, tout ce qu'il a besoin de savoir comment obtenir le nom de l'étudiant. En fournissant une interface pour étudiants à mettre en œuvre et de l'école à utiliser, il y a un accord entre les deux parties sur ce que la fonctionnalité est nécessaire par l'école pour effectuer son travail. Maintenant, nous pouvons passer dans et hors différentes implémentations de la classe des élèves tout ce que nous voulons sans affecter l'école (tant que nous mettons en œuvre la même interface à chaque fois).

L'idée avec des classes abstraites est que vous pouvez toujours avoir une variable déclarée avec ce type (par exemple, il est le type statique), mais la variable fait référence en fait ou des points à un type de béton réel (le type dynamique).

Lorsque vous invoquez une méthode en C ++, le compilateur doit faire en sorte que la méthode serait pris en charge sur cet objet.

En déclarant la fonction virtuelle pure, vous mettez un « espace réservé » que le compilateur peut utiliser pour dire « oh ... Je sais que tout ce qui finit par être appelé par cette variable acceptera cet appel » parce que le béton réel types vont mettre en œuvre. Cependant, vous ne devez pas fournir une implémentation dans le type abstrait.

Si vous ne déclarez rien, alors le compilateur aurait aucun moyen efficace de garantir qu'il serait mis en œuvre par tous les sous-types.

Bien sûr, si vous vous demandez pourquoi vous voulez faire un résumé de la classe, il y a beaucoup d'informations autour de ce sujet.

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