Если есть разумное поведение по умолчанию для функции, на которое можно положиться в большинстве детей, она может быть реализована как нормальная. В противном случае (поведение по умолчанию отсутствует и / или большинству потомков не нужно его переопределять), лучше объявить его абстрактным. Побочным эффектом является то, что вы никогда не забудете определить его в дочернем классе, поскольку об этом будет немедленно сообщено.
Другой возможностью является использование контейнеров (например, массивов) для данных, которые являются специфическими для дочерних классов, но все же подлежат общим проверкам или другой обработке, которая может быть выполнена в общем предке. Таким образом, вы определяете переменную, которая содержит данные, но сами данные заполняются дочерними элементами. Код в родительском классе может перебирать этот контейнер и выполнять некоторую рутинную работу над всеми элементами.