Pensare che ogni lingua OO (e in realtà, Turing completa) debba essere "appresa" separatamente è un approccio sbagliato. Fidati di me, anch'io ho iniziato così, e poi ho ripensato all'intero approccio. L'idea qui è di familiarizzare con le nozioni di base comuni a tutti i linguaggi di programmazione, come il modo in cui le variabili funzionano, come funzionano i riferimenti e i puntatori, cosa succede con funzioni / metodi e quindi con strutture dati, classi e oggetti.
Quindi esamina le buone pratiche di codifica di base: i principi OO (almeno quelli principali), vari tipi di test automatici per il tuo codice, ecc.
Usa la lingua con cui hai già familiarità per esplorare tutti questi aspetti. Una volta che hai compreso bene questi concetti di base, familiarizzare con una nuova lingua sarà un gioco da ragazzi.
Sì, certo, ogni lingua ha le sue specifiche, come potrebbero trattare funzioni o oggetti di variabili leggermente diverse tra loro, ma hanno molto più in comune di quanto non abbiano discrepanze.
E non cadere nella trappola di pensare che l'apprendimento di un certo linguaggio dipenda principalmente dalla conoscenza a memoria delle API delle principali librerie e strutture di terze parti create per quel linguaggio. Soprattutto quadri. Questo è qualcosa di cui soffrono Java e JavaScript. Non è colpa loro, è il modo in cui alcune persone pensano di affrontarle al meglio. Questo è un altro trabocchetto in cui mi sono imbattuto ad un certo punto. Ero più preoccupato dei nuovi trucchi che l'ultima versione di Spring Framework può fare piuttosto che pensare a come migliorare la mia codifica generale. Questo è meno un problema per linguaggi come C e CPP.
Proseguendo sull'ultima idea, i libri di Thinking in XXX di Bruce Eckel sono eccellenti. Finisci quello su Java e prova a codificarti il maggior numero possibile di esempi. Quindi prova a pensare in C / CPP, seguito da alcuni libri sui test unitari e funzionali. Poi vai su roba su strutture dati e algoritmi, questo è uno dei miei preferiti sull'argomento: link