Learning by doing is most critical.
Quite often theories themselves may look exciting or boring - but unless we put things in practice, we don't really get a real feel for what it means. The point that drives the learning is when we have real questions raised in our minds - quite often beyond what text books poses.
It is very important that you chase behind something which is worth it. As we do things - we evolve our thinking. you will see yourself from asking "how-can-i-do-this" to "why-does-it-work-the-way-it-is".
Now coming to the concrete answer to your question. Here are some simple suggestions:
Learning process for you will have critical steps.
1. Problem Solving
The first thing to learn is learning a language as a problem solving tool.
This will start with learning the programming syntax and semantics. (this is enough learned through the class room assignments. And later you should try to implement Data structures and Algorithms on your own.
You can study from many possible books and implement something on your own.
by this time, you should be able to solve problems well using C++.
2. Learning elegant design
One of the most important corner stone for being able to write good programming is to be able design good object oriented code. This is essential. My personal favorite book is from James Rambaug. What is important is that you must get concrete reasoning - ask why rather than how about learning this.
At this stage - learning would be best when you take up some full project on your own. I would strongly advice that you should do an assignment on your own fresh rather than start some existing code at this stage. It should be small, but it must have some good puzzle in it.
Only when you look at multiple object/ algorithms interacting you will learn that there is a good deal of possibility when you take the problem as good-design rather than just-make-it-work.
3. Learning software development practices
Finally, as you manage to write a full-thing on your own, and would have solved issues that pained you, now, by the time you have got to this stage, you will begin to realize that there are good-ways-of-doing and bad-ways-of-doing. This is where practices comes in place.
You can refer to the books like "Effecitve C++" as already pointed by many. Also, i would add another book in reference as "Code complete".
At this stage you must take up a fully functional Open source project to see how things work. Take up something small but that excite you; and at once - you will find many things a bit not-so-obvious.
As you grow with some of the projects - you will begin to see blend of great-problem-solving, elegant-design and dependable-practices. That's all it takes to become a good software engineer!
Important thing is to remember to ask - How and why at all times.
One final reference. Read this: Teach yourself programming in 10 years.
I don't know how much you have actually reached, but you can guide yourself to this.