2017-06-20 1 views
1

J'essaye de surcharger la fonction add() dans la classe héritée NumericInput. Mais lorsque j'appelle add() sur un objet NumericInput, la fonction add() de la classe de base est appelée. Pourquoi est-ce?Méthode de remplacement en C++

#include <iostream> 
#include <string> 

class TextInput 
{ 
public: 
    std::string cur; 
    void add(char c) 
    { 
     cur += c; 
     std::cout<<"input is: "<<c<<'\n'; 
    } 

    std::string getValue() {return cur;} 
}; 

class NumericInput : public TextInput 
{ 
    public: 
    void add(char c) 
    { 
    if(c>=48 && c <= 57) 
    { 
     std::cout<<"input is a digit: "<< c <<'\n'; 
     cur += c; 
    } 
    else 
    { 
     std::cout<<"input is not digit"<<'\n';} 
    } 
}; 

int main() 
{ 
    TextInput* input = new NumericInput(); 
    input->add('1'); 
    input->add('a'); 
    input->add('0'); 
    std::cout << input->getValue(); 
} 
+3

Faites-le 'virtuel'. – songyuanyao

+0

L'appel d'une méthode d'un pointeur à la classe de base appelle toujours la fonction de membre de la classe de base sauf si cette fonction est virtuelle. –

Répondre

1

Comme dit dans le commentaire, faire virtual. Il est également recommandé de marquer la fonction principale avec override. De cette façon, vous obtiendrez une erreur de compilation quand il n'y a pas de fonction à remplacer (généralement à cause d'une faute de frappe dans le nom).

De plus, toute classe avec des fonctions virtuelles doit avoir un destructeur virtuel afin de pouvoir être supprimé via un pointeur. Ne pas oublier de supprimer le pointeur aussi bien!

#include <iostream> 
#include <string> 

class TextInput 
{ 
public: 
    std::string cur; 

    virtual ~TextInput() = default; 

    virtual void add(char c) 
    { 
     cur += c; 
     std::cout<<"input is: "<<c<<'\n'; 
    } 

    std::string getValue() {return cur;} 
}; 

class NumericInput : public TextInput 
{ 
public: 
    virtual void add(char c) override 
    { 
     if(c>=48 && c <= 57) 
     { 
      std::cout<<"input is a digit: "<< c <<'\n'; 
      cur += c; 
     } 
     else 
     {std::cout<<"input is not digit"<<'\n';} 
    } 
}; 

#ifndef RunTests 
int main() 
{ 
    TextInput* input = new NumericInput(); 
    input->add('1'); 
    input->add('a'); 
    input->add('0'); 
    std::cout << input->getValue() << '\n'; 
    delete input; 
} 
#endif 

Ceci est également un bon endroit pour appliquer le langage d'interface non-virtuelle . La classe de base a une fonction membre add qui n'est pas virtuelle et qui prend en charge l'ajout du caractère à la chaîne cur. Il le fait si do_add signale que le caractère doit être ajouté. La fonction do_add est virtuelle et, surtout, privée. Cela assure l'encapsulation et rend la classe portable. Reportez-vous à l'article 35 "Prise en compte des alternatives aux fonctions virtuelles" dans En vigueur C++ par Scott Meyers.

De même, utilisez un std::unique_ptr pour gérer la mémoire de votre classe.

#include <iostream> 
#include <string> 
#include <memory> 

class TextInput 
{ 
    std::string cur; 

    virtual bool do_add(char c) 
    { 
     std::cout<<"input is: "<<c<<'\n'; 
     return true; 
    } 

public: 
    virtual ~TextInput() = default; 

    void add(char c) 
    { 
     if (do_add(c)) 
      cur += c; 
    } 

    std::string getValue() 
    { 
     return cur; 
    } 
}; 

class NumericInput : public TextInput 
{ 
    virtual bool do_add(char c) override 
    { 
     if (c>=48 && c <= 57) 
     { 
      std::cout<<"input is a digit: "<< c <<'\n'; 
      return true; 
     } 

     std::cout<<"input is not digit"<<'\n'; 
     return false; 
    } 
}; 

#ifndef RunTests 
int main() 
{ 
    auto input = std::unique_ptr<TextInput>{new NumericInput()}; 
    input->add('1'); 
    input->add('a'); 
    input->add('0'); 
    std::cout << input->getValue() << '\n'; 
} 
#endif 
+0

Merci pour vos réponses détaillées. Pouvez-vous expliquer l'utilisation de {new NumericInput()}? std :: unique_ptr {nouveau NumericInput()} –

+0

@LeiWang http://fr.cppreference.com/w/cpp/memory/unique_ptr –