Department of Engineering

IT Services

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