 |
Department of Engineering |
 |
 |
C++ for C programmers
Introduction
First there was B. Then there was C, which attained unofficial standardisation
when Kernighan and Ritchie's 1st book came out. While C++ was being
developed, C developed too, borrowing ideas for C++ to become "ANSI C"
(or C89). C++ became official in 1997, care being taken to at least include
all the C keywords in it.
In September 1999 a new C codenamed
C9X was ratified, introducing some keywords that C++ doesn't have.
Are you going to learn the latest C or move on to C++? Or maybe try java??
Some people say that C programmers might be best advised to start writing
C++ in "the C++ way" right from the start but Stroustrup's not against
a gradual transition, initially using C++ as if it were just "a better version
of C". C++ doesn't force you to work in a particular way. It supports 3 main
methodologies: procedural (like C), Object-orientated,
and Generic (as with the Standard Library algorithms).
Procedural programming
Some small-scale changes do not require a lot of work.
- strings - easy to use. Safe, and provides experience of using
C++ objects - s.length() is a string's length, for example.
But with the overheads that objects involve what about speed? Two points
are worth bearing in mind here, and more generally too
- You should compare like with like. It's not fair to compare
C++'s "s+=t;" with C's "strcat(s,t);" - the latter by itself
isn't safe.
- Objects can speed things up. C's "strcat" has to chug through
"s" to find the end, but C++ can keep a note of the string's length.
- references - safer than pointers
- I/O - type-safe
Object-orientated programming
Some often mentioned advantages of object-oriented programming are: faster development, increased quality,
easier maintenance, understandability and enhanced modifiability.
Implementation details are hidden and interfaces provide precise and
detailed instructions for the use of objects. Furthermore, an object-oriented approach is in many
cases more natural and appeals more to human cognition than other methodologies.
Some important object-oriented concepts are
- Objects and messages
- Encapsulation - hiding all
details of an object that do not contribute to its essential characteristics.
- Code reuse - Inheritance.
C supports some of these concepts to an extent, but becomes unwieldy,
especially when C's lack of operator redefinition means that new
types of objects can only be "added together" by calling functions.
Generic programming
The Standard Library contains lots of routines to
deal with common data structures - sets, lists, vectors, etc. The same
routine name can be used on different types of objects.
See the
Standard Template Library talk for examples.
C habits to give up
C++ is a flexible language. You can write C++ that a C compiler could compile
(though behaviour might be different).
You can even write in a style that isn't too distant from Fortran 77. But
if you're a C programmer who wants to make the most of modern C++, the following
points are worth bearing in mind
- Think in terms of objects rather than functions and data. Groups of
objects are easier to organise (using inheritance) than are groups of
functions. Rather than sending data to routines, send "signals" to
objects.
- Use namespaces: functions can have shorter names; information hiding
is easier; and it's easier to switch between different implementations.
Use namespace rather than files to control scoping.
- Use strings. You can convert between C and C++ strings
char cstring[]="a test";
string a_str;
a_str=string(cstring);
strcpy(cstring, a_str.c_str());
- Don't use NULL - use 0
- Create variables just before first use. In particular, create for
loop index variables within the loop construction.
- Use exceptions when the code that has to deal with a problem is
far from the code that discovers the problem.
- Use const as much as possible. Note that in C++,
const variables have internal
linkage by default whereas in C they have external linkage.
- Use enum
- Don't use type-identifer fields in structures
- Avoid pre-processor macros -
const, inline, template and namespace
replace most of #define usage,
leading to stronger typing and better control of scope.
Here are 2 examples
const int answer = 42;
template<class T> inline T min(T a, T b) {return (a<b)?a:b;}
- Be careful with casts. C++ is on the way to banning the
"(int) f" style of casts completely.
- Avoid static except within functions.
// better than a global
int & use_count()
{
static int uc =0;
...
return uc;
}
or use nameless namespaces
namespace {
class X{};
void f(); // like a static - private to namespace scope
int i;
}
References