Да, важно. Да, речь, в основном, про наследование. Да, наследованием на начальном этапе многие злоупотребляют. Типичный и один из самых распространенных "паттеров", когда это заведомо нужно (и алтернативные рекомендуемые подходы почти не работают) - это когда Вы в контейнер (вектор, массив и тп) закладываете [умные или глупые] указатели на чуток разные, но похожие по смыслу объекты.
Сужающее - преобразование в тип, включающий не все значения базового. Например, вещественного числа в целое. Расширяющее - в тип, содержащий больше значений, чем базовый. Например, целое число в вещественное.
Насколько это важно - как я тебе это оценю? на 17
Для программирования на C++ надо знать возможные преобразования типов, особенно автоматические, вот и все.
Если уж конкретно C++, а не C, то речь идет о преобразовании из производного класса в базовый и наоборот. Первое - сужающее, и оно всегда корректное. Второе - расширяющее, опасное. По крайней мере если делать через бабушкины методы типа derived_pointer = (Derived*)base_pointer либо через static_cast. Через dynamic_cast будет безопасно. Правда, dynamic_cast включит RTTI, и будет жрать ресурсов чуток побольше