@Fred Nurk has already posted a link to the book list, so I won't try to go into detail, but I'd consider Accelerated C++ the first book on that list to study from.
As for an example, let's consider a fairly simple program: a simplified version of the standard Unix "sort" command. To keep the code short (but still at least a little interesting), let's have it operate as a filter, and produce results roughly equivalent to sort -u. In C with Classes type code, you might typically see something on this order:
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
const int max_lines = 1024 * 1024; // allow up to one megaline of input.
int sort_func(void const *a, void const *b) {
return strcmp(*(char const **)a, *(char const **)b);
}
int main() {
char buffer[1024];
char **lines;
unsigned current_line = 0;
lines = new char *[max_lines];
while (cin.getline(buffer, sizeof(buffer))) {
char *temp = new char[strlen(buffer) + 1];
strcpy(temp, buffer);
lines[current_line++] = temp;
if (current_line == max_lines)
break;
}
qsort(lines, current_line, sizeof(lines[0]), sort_func);
cout << lines[0];
for (int i=1; i<current_line; i++)
if (strcmp(lines[i], lines[i-1]))
cout << lines[i] << "\n";
for (int i=0; i<current_line; i++)
delete [] lines[i];
delete lines;
return 0;
}
Now, this isn't particular terrible code (if I was being entirely honest, I'd probably make it worse). It passes the buffer size to getline, so the buffer won't overflow. It then allocates a buffer for a line, copies the data to the buffer, and goes on to the next. It even checks for the end of file correctly, etc.
Let's compare that to how I'd probably write the code in C++:
#include <iostream>
#include <iterator>
#include <set>
#include <string>
class line {
std::string data;
public:
operator std::string() const { return data; }
friend std::istream &operator>>(std::istream &is, line &l) {
return std::getline(is, l.data);
}
};
int main() {
std::set<std::string> lines((std::istream_iterator<line>(std::cin)),
std::istream_iterator<line>());
std::copy(lines.begin(), lines.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
This version is clearly a bit shorter. We've also eliminated most of the fixed limits such as the maximum line length and maximum number of lines. More importantly, however, it contains no explicit loops -- the input loop is handled implicitly in the constructor for the set, and the output loop is handled in the call to copy. Sorting and eliminating duplicates is implicit in the definition of set.