至于说在注释,使其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
使其成为'虚拟'。 – songyuanyao
调用指向基类的指针的方法将始终调用基类成员函数,除非该函数是虚拟的。 –