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