#c #overriding #c 17
#c #переопределение #c 17
Вопрос:
Итак, у меня есть базовый класс, который создан для хранения строкового значения и может добавлять в него символы:
class TextInput
{
public:
std::string value;
void add(char c)
{
if (!value.empty())
{
value = c;
}
else
{
value = c;
}
}
std::string getValue()
{
return value;
}
};
Затем наследуемый класс, который такой же, как родительский, но должен позволять вам добавлять числовые значения только в строку:
class NumericInput : public TextInput
{
public:
TextInput input;
void add(char c)
{
if (isdigit(c))
{
input.add(c);
}
}
std::string getValue()
{
return value;
}
};
Что я хочу знать, так это то, что при таком вызове в моих тестах:
#ifndef RunTests
int main()
{
TextInput* input = new NumericInput();
input->add('1');
input->add('a');
input->add('0');
std::cout << input->getValue();
}
#endif
Почему вызов add по-прежнему использует только базовый класс add ? Я бы предположил, что это использует дочерний класс NumericInout, поскольку он создается как один, но при отладке он по-прежнему использует только родительский класс, и я не понимаю, почему?
Комментарии:
1. В показанном коде нет ничего переопределенного. Если вы откроете учебник по C на главе, в которой объясняются виртуальные функции, вы узнаете, как правильно переопределять функции в базовом классе.
2. @Sam дочерний
add()
элемент переопределяет базовыйadd()
, не так ли?3. Нет, это не так. C так не работает. C — это не Java. Что-то еще должно быть сделано для того, чтобы он действительно переопределил его. Дополнительную информацию см. В вашем учебнике по C .
4.
override
также может быть полезно.5.Вам нужно создать
add
virtual
в базовом классе. Использованиеoverride
модно (повышает надежность), но не обязательно. C — это не Java, которую вы знаете: классы по умолчанию не являются полиморфными. Также наличиеTextInput input;
в качестве члена дочернего класса, хотя иногда это полезный шаблон, скорее всего, является ошибкой.
Ответ №1:
class NumericInput : public TextInput
{
public:
TextInput input;
Это почти наверняка не то, что вы хотите. Если вы наследуете, я не могу придумать веской причины, по которой вы когда-либо хотели бы использовать композицию. Избавьтесь от этой input
переменной-члена. При наследовании вы уже получаете все из родительского класса (в том числе value
и в этом случае).
Чтобы конкретно вызвать родительский класс add()
, вы можете сделать TextInput::add()
, чтобы ваш дочерний add мог выглядеть так:
void add(char c)
{
if (isdigit(c))
{
TextInput::add(c); // Call parent add()
}
}
Кроме того, если вы хотите вызвать add()
TextInput
указатель, который указывает на a NumericInput
, и вы хотите, чтобы он разрешал вызов NumericInput
‘s add()
, вы должны объявить базовое add()
значение равным virtual
:
virtual void add(char c) { // ...
Наконец, вы все равно можете добавлять к строке, даже если в ней ничего нет, поэтому ваша проверка в базе add()
ничего не делает.
В целом, это сделает ваш код похожим:
class TextInput
{
public:
std::string value;
virtual void add(char c) { value = c; }
std::string getValue() { return value; }
};
class NumericInput : public TextInput
{
public:
void add(char c)
{
if (isdigit(c)) { TextInput::add(c); }
}
// You already get this for free from the inheritance
// std::string getValue()
// {
// return value;
// }
};
Живой пример здесь: https://ideone.com/kQxAPo
Комментарии:
1. Добавьте ключевое слово override в add . С таким же успехом можно научить хорошим привычкам.
2. @Yakk-AdamNevraumont: сегодня я чувствую себя очень педантичным:
override
это идентификатор с особым значением, а не ключевое слово. Хороший ответ, хотя, 1.3. @bash это контекстное ключевое слово, более разговорное и понятное. Идентификатор со специальным значением является стандартным, а иногда о стандартах говорить бесполезно. для людей с. 😉
4. @Yakk-AdamNevraumont: Я упоминаю об этом только потому, что вы все равно можете использовать
override
в качестве имени класса, имени функции или имени переменной. Его введение не нарушило существующий код. (см. decltype ).5. Большое спасибо! Вроде как изучаю это на лету из фона C #. Я ценю подробный ответ!