FAQ Articles Links Personal

Recommended books

  1. Why do I need books to learn C++ ?
  2. Novice C++ books.
  3. Intermediate C++ books.
  4. Advanced C++ books.

Tools

  1. Where can I get a compiler for my platform ?
  2. What Integrated Development Environments can you recommend ?
  3. What are the commercial alternatives ?

Common errors

  1. The C++ standard: ISO/IEC 14882-2003.
  2. The "Hello, world!" program.
  3. The C headers in C++.
  4. Unexpected end of file while looking for precompiled header directive.

Input and Output

  1. Basic C++ I/O.
  2. How do I write a simple file reader ?

Pointers

  1. What are pointers and why would I use them ?
  2. Why shouldn't I use pointers everywhere ?
  3. What are smart pointers ?

Classes

  1. Why would I write my programs in an Object Oriented way ?
  2. What's the deal with the access specifiers ?
  3. Why shouldn't I make everything public ?
  4. What does "const correctness" actually mean ?

Inheritance

  1. Why does C++ need inheritance ?
  2. What's the difference between public, protected and private inheritance ?
  3. What are virtual functions ?

Templates

  1. What are templates ?
  2. How do I convert from string to int ?
  3. Why do I get unresolved externals ? I implemented the function members !

Namespaces

  1. How to alias an object from another namespace with a new name in the current namespace ?

 

Recommended books

Why do I need books to learn C++ ?

The C++ programming language is quite complex. The C++ ISO standard has about 750 pages of rigid descriptions, unusable for inexperienced programmers. It was not conceived as a learning textbook, but as a standard for compiler writers and advanced programmers to use as a reference. Unfortunately, there aren't very good tutorials online, and nothing is like a book written by professionals.

Besides, learning how to program in C++ is not about knowing every function or class the standard describes. Learning how to program in C++ means understanding the language itself (what it offers, what you can and can't do with it) and knowing design patterns to help you write good, manageable code. This can only come from the experience gained by programming and reading books.

 

Novice C++ books

I recommend Stampile konadby Andrew Koenig and Barbara E. Moo as the best introductory C++ book. It doesn't assume you have a programming background, but starts off pretty fast. With this book, and some programming practice you should become an intermediate C++ programmer reasonably fast.

 

Intermediate C++ books

 

Advanced C++ books


Tools

Where can I get a compiler for my platform ?

You can find most freeware compilers at compilers.net. I recommendGCC as the best OpenSource compiler. You can use the Win32 port of GCC, mingw, on Windows.

 

What Integrated Development Environments can you recommend ?

 

What are the commercial alternatives ?


Common errors

The C++ standard: ISO/IEC 14882-2003.

In order to make sure we talk the same language, be it a programming language, a standard must be developed. The C++ programming language is no different. It helps programmers move from a compiler to another, or from a platform to another. It is also crucial for portability - say you want to make a program that works on both Windows and UNIX. If your compiler didn't offer implementations on both operating systems, and there were no standard - it would be a difficult task. Even with a C++ standard and compilers that follow it (up to some degree), this is a difficult task sometimes, due to the differences between the operating systems. However, writing standard C++ code, without any additional libraries (such as network sockets, GUI artifacts, etc) should work without modifications.

 

The "Hello, world!" program.

#include <iostream>

int main( ) {

std::cout << "Hello, world!" << std::endl;

}

 

The C headers in C++.

Every standard C header can be found in C++, under a slightly different name. If <header.h> was a header in C, then the equivalent C++ header would be <cheader>. No C++ headers have the .h extension anymore. For example, <stdlib.h> is <cstdlib>, <time.h> is <ctime>, <string.h> is <cstring> (not to be confused with <string> ), etc.

 

Unexpected end of file while looking for precompiled header directive.

Just open one of your .cpp files and add:

#include <stdafx.h>


Input and Output

Basic C++ I/O

C++'s I/O is a lot easier than C's. In C, you had the redundancy of declaring the type twice: once in the type declaration and then in printf or scanf. C++ avoids that using I/O streams. For instance, if you want to read the name and age of the user, and then output them all you have to do is:

#include <iostream>

#include <string>

int main( ) {

unsigned int age;

std::string name;

std::cin >> name >> age; // will read name and age in that order

std::cout << "Hello, " << name << ". You are " << age << " years old." << std::endl;

}

Note that you only had to worry about the type once: at the declaration. In C, you have to declare it and then remember to use the right format string in printf or scanf.

 

How do I write a simple file reader ?

#include <iostream>

#include <string>

#include <algorithm>

#include <iterator>

#include <fstream>

#include <vector>

int main( ) {

std::ifstream fileStream( "path\\to\\file.ext" );

std::vector< std::string > vec;

std::copy(

std::istream_iterator< std::string >(fileStream),

std::istream_iterator< std::string >(),

std::back_inserter( vec )

); // now vec has all the words in the file, as its elements

}


Pointers

What are pointers and why would I use them ?

Pointers are objects that hold a memory address. You can perform arithmetical operations on them (for instance, move the pointer to the immediate next memory location, etc), perform comparison operations between two pointers or dereference them. Dereferencing means accessing the pointed memory. Do not confuse the two: the arithmetical and comparison operations are made on the pointer itself. After dereferencing it, you are changing not the pointer, but the memory it points at. You can see it as a finger. You can have more fingers. More fingers can point at the same object (memory location). You can move the finger or test whether two fingers point to the same object. However, if you change the state of the object you are pointing to (by dereferencing), each finger that was pointing at that object will give you the changed object upon dereferencing.

Pointers must be used if you need to:

 

Why shouldn't I use pointers everywhere ?

Pointers are quite dangerous. If you declare a pointer and forget to initialize it to a value and use it, your program will most probably crash. If you have a pointer that already owns memory and you use it to store some other newly created memory, you will "lose" the "old memory", thus producing a memory leak. If you delete a pointer twice (in order to deallocate the memory), your program will most probably crash. If you pass a pointer to a function, you don't know what it will do. It might change your pointer, deallocate it, or change the object it points to.

Here's a list of usual pitfalls when using pointers:

As a rule of the thumb, never use pointers unless you have to. The alternative is using const references, especially as function arguments. It has all the advantages of pointers, plus:

 

What are smart pointers ?

Smart pointers are C++ objects that simulate simple pointers by implementing operator-> and the unary operator*. In addition to supporting pointer syntax, they also provide useful such as memory management and consequently, memory ownership. Most smart pointers do not provide the simple pointer arithmetic operations. The C++ standard provides a single implementation of smart pointers, namely std::auto_ptr. It provides memory management and it owns the memory it holds. Consequently, if you do something in the lines of smartPtr1 = smartPtr2, the memory smartPtr1 holds will be deallocated, smartPtr1 will hold the memory of smartPtr2 and smartPtr2 will hold no memory at all. It takes time to get used to this behavior, but it has numerous big advantages of which the most notable is escaping memory leaks in the presence of exceptions.


Classes

Why would I write my programs in an Object Oriented way ?

Object Oriented Programming (OOP) has numerous benefits:

 

What's the deal with access specifiers ?

Access specifiers help you customize who can and cannot access your members, be it functions or data. This table should shed some light on the problem:

function
public
protected
private
nonmember
yes
no
no
member
yes
yes
yes
derived member
yes
yes
no

 

Why shouldn't I make everything public ?

Consider, for example that you are writing a smart pointer class. If you made the member pointer public, someone might accidentally delete it. When the destructor is called, the same pointer will be deleted the second time, which will cause your program to crash. There are a lot of reasons you shouldn't make any of your data anything else than public. When you make a class, in your constructor you should make sure your data is valid. For instance, in a Date class, you would check if the months is in the interval [1,12], in a Socket class, you would create a valid socket file descriptor, etc. If any of these data members would be non-private, someone might change it, and your class will not be in a coherent state. If you have a need to give access to your members (and it makes sense to), you should do it in a controlled way:

const Type& MyClass::Get() const {

return my_member_;

}

void MyClass::Set( const Type& value ) {

if( value is valid depending on the context of MyClass ) {

my_member = value;

}

}

Let's start with the Get() member function. It returns a const reference because:

The Set() member function doesn't blindly changes the value of the member data. Usually it has to perform checks in order to be able to sustain the consistence of your object.

This might seem like a hassle, but with only a few lines of code you can avoid numerous problems.

 

What does "const correctness" actually mean ?

The keyword const translates to a guarantee. A guarantee made by the coder of a function to you, the caller, that his function will not change the state of an object. There are two types of const: const functions and const objects.

Const functions are always member functions of an object and can never change the value of any of its members. However, sometimes you might need to do that. Consider a Socket class. It would need to have a Read() function that will receive data from the network. Such a function would probably look like this:

std::string Socket::Read() const;

The function should be const because it should not change anything inside the Socket class. It just has to read some data and return it. This is easy to do, but what if you want to provide another function - a function that returns the total number of bytes received. In this case, the Read() function will have to change a member variable in your Socket class. The solution is not removing the const from Read() but making the receivedBytes_ member a mutable member. The syntax is:

mutable unsigned long receivedBytes_;

Mutable is a keyword that allows you to change the member's variable even in const functions. It was written specially to aid in such problems, as the one presented above.

Const objects cannot be changed in any way. You cannot change their value, or call any member function that is non-const. When used as arguments in functions, usually as a const reference, this means a guarantee that the object will not be changed. Consider smart pointer's operator= member. As a reminder, here's the operator= signature for type T:

T& operator=( const T& other );

Consider the operation smartPtr1 = smartPtr2. If we want to use memory ownership, then operator= should change smartPtr2's internal pointer. The problem is that you have to break the promise const gives as it is crucial for the smart_ptr class to work properly. The solution is to make the internal pointer member of smart_ptr mutable just as the case above with functions. There's a slightly better way to do this. You can add a mutable bool member in the smart_ptr class, which would indicate whether the smart_ptr still owns the pointer or not. If it doesn't, it shouldn't attempt to delete it or pass it to another smart_pointer. This way, you can avoid making a crucial member of smart_ptr mutable.

These are exceptional cases where using mutable members is crucial. Try and not overuse mutable members. If you do, then you're doing things wrong. The most important rule is never to make members that influence the coherence of the class mutable. Even if the receivedBytes_ or the boolean ownPointer members are mutable, they are not crucial for the state of the class.

As for const, the rule of the thumb is to make, where possible, everything const.


Inheritance

Why does C++ need inheritance ?

Inheritance is a very strong C++ mechanism to help build a class hierarchy and express, through code, relationships between classes. Perhaps the most used example is the Shape hierarchy design. Consider you want to build a simple Paint program. You would probably want to have a generic Shape class and have Circle, Triangle and Polygon inherit from it. Why ? There are quite a few reasons:

If you don't think that's enough, wait until we get to virtual functions and polymorphism.

 

What's the difference between public, protected and private inheritance ?

As with class access specifiers, inheritance access specifiers are best explained with a table. In this case, however, I would need a tri dimensional table, so I will split it in 3 tables. The header access specifiers are the inheritance specifier. The "derived member" refers to a derived class of the derived class. If the member (data or function) of the base class is public:

function
public
protected
private
nonmember
yes
no
no
member
yes
yes
yes
derived member
yes
yes
no

If the member (data or function) of the base class is protected:

function
public
protected
private
nonmember
no
no
no
member
yes
yes
yes
derived member
yes
yes
no

If the member (data or function) of the base class is private:

function
public
protected
private
nonmember
no
no
no
member
no
no
no
derived member
no
no
no

Note that the only way to ensure that your members won't be changed by anything else than your own class, you have to make it private.

 

What are virtual functions ?

Virtual functions cannot be explained before explaining polymorphism. When you publicly derive from a base class, you are allowed to use a base pointer to store a dynamically allocated derived object. For instance:

class Base {

public: void baseF() { std::cout << "Base::baseF()" << std::endl; } };

class Derived : public Base {

public: void derivedF() { std::cout << "Derived::derivedF()" << std::endl; } };

void func(){

Base b; b.baseF(); // outputs "Base::baseF()" as expected

Derived d; d.derivedF(); // outputs "Derived::derivedF()" as expected

Base * pd = new Derived;

pd->baseF(); // outputs "Base::baseF() as expected

pd->derivedF(); // compile error

delete pd; // undefined behavior - see below

}

If we can't even use the derived members, why bother using a pointer to the base class anyway ? Without virtual functions, this would make no sense at all, indeed. Before I go any further, I must say that even if you removed the line that causes the error, you would still have a problem: undefined behavior, in this case usually spelt as memory leaks. The static type of the object pd is Base* (as that is the type it was declared). The dynamic type is Derived*. Function lookups are done statically, so when deletion is attempted, the Base destructor is called - and here comes the problem, as our object is a Derived instance. In this case, we would need some sort of mechanism to be able to call Derived's destructor first. That is impossible because, as we saw, we can't call any of Derived's functions, because the static type is Base.

This is where virtual functions come into play. If we declared Base's destructor virtual, then the undefined behavior problem wouldn't exist. What does that mean ? It means that, when a function is virtual, then the compiler ignores the static type (only true for pointers or references; regular types only have a static type) and looks up the dynamic type, calling the appropriate function. Of course, in the case of destructors, the Derived's destructor will call the Base's destructor thus avoiding memory leaks.

Virtual functions were not added to the language just for destructors. Having destructors virtual is just a necessity to avoid memory leaks. Let's consider the Shape example. For simplicity, the Shape class, and derived classes will only have a Draw() function:

class Shape {

public:

virtual void Draw() const { } // we don't know how to draw any shape

virtual ~Shape() { }

};

class Circle : public Shape {

public:

void Draw( ) const { /* use system-specific code to draw a circle */ }

};

class Triangle : public Shape {

void Draw( ) const { /* use system-specific code to draw a triangle */ }

};

void foo ( ) {

Shape* ptr = new Circle; ptr->Draw(); // will call Circle::Draw()

delete ptr; // deletes the Circle properly

ptr = new Triangle; ptr->Draw(); // will call Triangle::Draw()

delete ptr; // deletes the Triangle properly

}

void bar( const std::vector<Shape*>& vec ) { // vec is a container holding concrete Shapes

for( std::vector::const_iterator iter = vec.begin(); iter != vec.end(); ++iter ) {

(*iter)->Draw(); // regardless whether the Shape* is actually a Triangle or Circle, the right Draw function will be called

}

}

The benefit this type of design gives is that you can use a single type, Shape* and you can get a dynamic response.

The rules of polymorphism are simple:


Templates

What are templates ?

If virtual functions are C++'s dynamic mechanism, templates are its static magic box. Consider you want to make a function that takes two numbers and returns the one with the greater value. You would probably start writing int max( int num1, int num2 ) or perhaps with longs or doubles. That would work, as integers can be automatically cast to a double or float. However, what if you wanted the function to work on other types too ? Such as a std::string ? Or any type that implements an operator<. This could prove tedious as the number of types increases. What if you could write a single function that can compare and return the right value for any object (built in or user-defined) if it has operator< defined ? That would save a lot of work, mistakes and recompilations.
Templates do just that. They provide a mechanism to write generic code, regardless of the types involved in the function. The only restrictions are the ones you make yourself. For instance, inside our max function, operator< shall be used, which means that if we try to use the function with types that don't define operator<, we will get a compile error. However, that makes sense. If the objects are comparable, then an operator< should be provided. Here's how you can do it:

template< typename T >

const T& max( const T& val1, const T& val2 ) {

return val1 < val2 ? val2 : val1;

}

What happens is that once you try to do something like int mval = max( i1, i2 ), the compiler will try to create the function you would have made if templates weren't available, namely replace every occurrence of T in the above code with int. The compiler "knows" it has to replace with int because the arguments of the function ( i1 and i2 ) have the static type int. If you used float, it would make another for float. Same goes for double, std::string, etc. If you would, however try that with an object without operator<, such as a std::vector, you would get a compiler error saying (more or less directly) that std::vector does not implement operator<.

 

How can I convert from string to int ?

Because we're in template-land, I will provide a more general way to do various conversions.

You want to make a function that converts from a type to another. Like from std::string to int, or the other way around. This can be done using std::stringstream and insertion / extraction operators. Just as above, templates will prove of great help:

template< typename FROM, typename TO >

TO lexical_cast( const FROM& object ) {

std::stringstream converter;

TO retval;

converter << object;

converter >> retval;

return retval;

}

Its usage is not as straightforward as the above explained max template. Normally, you would want to call it like "int value = lexical_cast( myStdString );". There is, however, a problem. The compiler cannot guess that the TO template type is an int, as return types are not passed to the function. So, we need to let the compiler know what kind of lexical_cast it has to create. We already tell him the FROM template type using the passed argument. What we need is to pass it the TO type as well. This is done by simply: int value = lexical_cast<int>( myStdString ).

 

Why do I get unresolved externals ? I implemented the function members !

This is a more delicate problem. To cut the story short, you need to write the implementation of your member functions in the same header you declare the class.


Namespaces

How to alias an object from another namespace with a new name in the current namespace ?

If you just wanted to bring the object to the current namespace, from namespace NS, you would just do:

namespace NS { Type objectName; }

namespace OtherNS { using NS::objectName; }

However, if you need it under a different name, the solution is:

namespace OtherNS { Type& newName = objectName; }

 

 


© Ciobanu Vladimir, 2004