2017-06-20 16 views
1

継承されたクラスNumericInputの関数add()をオーバーライドしようとしています。しかしNumericInputオブジェクトのadd()を呼び出すと、基本クラスのadd()関数が呼び出されます。どうしてこれなの?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

「仮想」にします。 – songyuanyao

+0

基本クラスへのポインタのメソッドを呼び出すと、その関数が仮想でない限り、常に基本クラスメンバ関数が呼び出されます。 –

答えて

1

コメントに記載されている通り、virtualとします。上書きする関数にoverrideとマークすることも良い方法です。そうすれば、オーバーライドする関数がないとき(通常は名前のタイプミスのために)、コンパイラエラーが発生します。

仮想関数を持つクラスには、ポインタを使用して削除できるように仮想デストラクタが必要です。ポインタも削除することを忘れないでください!

#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 

これも非仮想インターフェイスイディオムを適用するには良い場所です。基本クラスには、仮想ではないメンバ関数addがあり、文字を文字列curに追加します。 do_addが文字を追加する必要があると報告した場合はそうです。機能do_addは仮想であり、最も重要なのはプライベートです。これにより、カプセル化が確実に行われ、クラスが移植可能になります。 Scott Meyers著、Effective C++の項目35「仮想関数の代替を検討する」を参照してください。

また、std::unique_ptrを使用して、クラスのメモリを管理してください。

#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

詳細な回答ありがとうございます。 {new NumericInput()}の使用方法について説明できますか? std :: unique_ptr {new NumericInput()} –

+0

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

関連する問題