コメントに記載されている通り、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
基本クラスへのポインタのメソッドを呼び出すと、その関数が仮想でない限り、常に基本クラスメンバ関数が呼び出されます。 –