I love C++ for the flexibility that it offers, and with the arrival of libraries such as BOOST it is becoming easier to piece together a powerful application with most of the time spent concentrating on the business logic.
However, here are some common examples where code will compile but not do what was intended.
1) Overriding Functions
class Base {
virtual void foo () const
{
// Default beahviour
}
};
class Derived : public Base {
virtual void foo ()
{
// Do something useful for Derived
}
};
It was almost certainly not the intention of the author that 'foo' in the derived class does not override the 'foo' in the base. You have to make sure your testing is really up to scratch to make sure that you can detect that Derived::foo
is not being called!
2) Operators that short-cut except when they don't:
class A {};
A foo (int * i)
{
*i = 0;
}
bool operator && (int *, A const &);
// ... lots of space between declaration and usage
void bar (int * i)
{
if (i && foo(i))
{
}
}
Others have mentioned operators, but there are 4 which are especially problematic. In the above example rather than having the usual "evaluate the first operand and if true then the second" what we actually have is a function call operator&&(i, foo(i))
. The first argument i
and the second foo(i)
. Both will be evaluated (in some unspecified order) and this will result in a null pointer dereference in foo
. The other operators to watch out for are, logical or (||), comma (,) and unary &.
3) Class member initialization that doesn't initialize:
class B
{
public:
B ();
};
class A
{
public:
~A();
private:
B b;
int i;
};
The above class the non-POD member i
is not initialized by the default constructor for the class. The same applies if the constructor was written as:
A ()
{
}
or
A ()
: b ()
{
}
Of course - what you need is some form of static analysis tool which will catch all of these niggling problems for you! ;)