The SLIME REPL must have some way of knowing that the input is finished. Simply inserting a newline does not inform it of this; instead, as Seibel suggested, there is a command `slime-repl-return' that does send the input if it is finished, and which RET is usually bound to in the REPL. `slime-repl-return' also, incidentally, if the input is incomplete, automatically indents, so you don't need to do anything special to get that behaviour.
The way you're setting up key bindings is a little weird. Locally set key bindings will shadow any others, I believe, and since the SLIME REPL uses a mode that runs lisp-mode-hook you're defining a key binding that will always shadow `slime-repl-return'.
A better way to do this is to make the key bindings in the key maps used by the various modes. I think the C++ mode uses `c++-mode-map', and all Lisp modes use `lisp-mode-shared-map'. This code will set up these key maps with the binding you want, without shadowing any bindings that the SLIME REPL wants:
(define-key lisp-mode-shared-map (kbd "RET") 'newline-and-indent)
(eval-after-load 'cpp ; This will wait until the C++ mode is ; loaded, and `c++-mode-map' defined, ; before running the code. '(define-key c++-mode-map (kbd "RET") 'newline-and-indent))