Reputation: 181
I am trying to override function add()
in the inherited class NumericInput. But when I call add()
on a NumericInput object the add()
function in the base class is called. Why is this?
#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();
}
Upvotes: 1
Views: 976
Reputation: 33
I would suggest using :
bool my_isdigit(char ch)
{
return std::isdigit(static_cast<unsigned char>(ch));
}
in order to verify that your char is digit or not
Upvotes: 0
Reputation: 10939
As said in the comment, make it virtual
. It is also good practice to mark the overriding function with override
. That way you will get a compiler error when there is no function to override (usually because of a typo in the name).
Also any class with virtual functions should have a virtual destructor so that it can be deleted via a pointer. Don't forget to to delete the pointer as well!
#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
This is also a good place to apply the non-virtual interface idiom. The base class has a member function add
which is not virtual and takes care of add the character to the string cur
. It does so if do_add
reports that the character should be added. The function do_add
is virtual and, most importantly, private. This ensures encapsulation and makes the class portable. See Item 35 “Consider alternatives to virtual functions” in Effective C++ by Scott Meyers.
Also, use a std::unique_ptr
to manage the memory of your class.
#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
Upvotes: 1