2017-06-20 145 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 –