И как правильно определить какой клас можно от какого наследовать, и по каким признакам можно определить что нельзя и это плохая идея?
мне на эту тему понравилась глава 32 из книги Скотта Майерса "Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ", можете погуглить.
глава называется "Используйте открытое наследование для моделирования отношения «является»"
и общая суть там ворочается вокруг
"Если вы пишете класс D (derived – «производный») открыто наследует классу B («base» – «базовый»), то тем самым сообщаете компилятору C++ (а заодно и людям, читающим ваш код), что каждый объект типа D является также объектом типа B, но не наоборот. Вы говорите, что B представляет собой более общую концепцию, чем D, а D – более конкретную концепцию, чем B. Вы утверждаете, что везде, где может быть использован объект B, можно использовать также объект D, потому что D является объектом типа B. С другой стороны, если вам нужен объект типа D, то объект B не подойдет, поскольку каждый D «является разновидностью» B, но не наоборот."(с)
В вашем же случае наследование юзера от DB можно интерпретировать как "пользователь является базой данных" - чувствуете что здесь что-то не то?