Se la gestione dei messaggi delle varie finestre deve essere differente in maniera significativa conviene avere più window classes, ognuna con la sua window procedure; se invece il grosso del codice è condiviso (le finestre di base sono sostanzialmente equivalenti), usa un'unica window class e disambigua quale finestra stai trattando nella window procedure (tipicamente si fa associando un puntatore ad una struct come "dati utenti" associati ad una finestra - vedi SetWindowLongPtr & co.).

In realtà, comunque, quando si lavora in C++ la costruzione che si fa è di questo tipo:
- una classe C++ va a corrispondere ad una window class, registrata al momento della prima creazione di un oggetto di quel tipo (puoi usare un campo static a questo proposito); la window class in questione usa come window procedure un metodo static della classe;
- ad ogni istanziazione della classe C++, si crea una finestra (basata sulla window class associata alla classe) e si memorizza this nei "dati utente" associati alla finestra con SetWindowLongPtr;
- dentro alla window procedure (che, ricordo, è static) si può quindi recuperare la specifica istanza della finestra su cui si sta lavorando usando GetWindowLongPtr.

In ogni caso, l'impressione che ho è che tu non abbia ben presente come siano strutturate le API Win32 di gestione delle finestre, prima di avventurarti in un terreno spinoso come questo dovresti quantomeno leggerti un po' di documentazione o (meglio) un buon libro in proposito.