This is a hypertext version of chapter 14 of the book Handbook of Software for Engineers and Scientists, published by CRCPress in 1996. Please read the Introduction section to understand the context in which this was written.
Table of Contents
1.0 Common Ideas
This short section considers common issues of code organization, declaration and definition, scope, binding and typing. These important ideas are used later in the language sections.
1.1 Files and C
C programming involves three file types: header files, with .h extensions; source files with .c extensions, and libraries, with various extensions (.lib and .a are both common). Header files usually contain variable, type and function declarations and pre-processor macros. These declarations are included in the source files which need them with a pre-processor directive, the #include. Source files are compiled to object files (often a .o extension), and the object files are linked with the appropriate libraries to make an executable program file. The same system of files is used in C++ and Objective C.
Object-oriented programming makes a fundamental distinction between interface and implementation. A common way of writing the code for a custom class mimics this dichotomy; a header file contains the interface to a class, a source file contains the implementation of the class methods. Class hierarchies can be placed in libraries to which header files serve as the roadmap.
1.2 Declaration and Definition
Understanding the difference between declaration and definition is essential to understanding C programs. A declaration of a variable or function is simply a statement of its type and name, and in the case of functions, its parameter list. Declarations allow the compiler to do type checking. Something may be declared as many times as is necessary to inform the compiler about the thing being declared. Multiple declarations are implicitly part of using the #include pre-processor facility, since multiple source files may #include the same declarations. With ANSI C, the compiler must see a declaration for a thing before it can use that thing. The declaration of a function is known as its prototype.
In contrast to declarations, a thing (variable, function or object) must be defined once and only once. Multiply defined things result in errors at compile-time. When the compiler sees the definition of a thing, it allocates memory for it. The definition of a function is the body of code for that function.
Scope is the area of a program in which the name of a variable, function or object is visible. C++ and Objective C offer three kinds of scope: global, local and class. Global scope is done just as in C, by defining the variable outside of any function or class scope. The static modifier can be used to limit global scope to a single file. Local scope is provided for automatic variables (those defined within functions). Class scope is provided for data members of a class, and encompasses all of the methods of the class.
1.4 Typing and Binding
Typing refers to the association of a variable with a data type. Strongly typed languages are those which enforce the assignment of values which match the declared type of a variable. The advantage of strong typing is that the compiler can find errors at compile time by checking that, for instance, function arguments match the type declaration of the function, and that function return values are assigned to compatible type variables. The original C language was not strongly typed. ANSI C is more strongly typed than C. The other consideration of the typing issue is when checking should be performed. Static type checking is done at compile time. Dynamic type checking is done at run-time. Dynamic type checking results in error messages at run-time when a type error is encountered.
Binding refers to the association of a function call or message to the actual code to execute. Object-oriented languages fall into two camps, static binding and dynamic binding. Dynamic binding means deferring the decision about what code is executed for a given message until run-time. The class of the receiving object is not determined until the time the message is sent, so the code which is executed can be determined by the class of the receiver. Static binding determines the code to execute at compile time, based on the type of the variable used to message the receiving object. Pointer variables allow the type of the receiving object to differ from the type of the pointer used to send the message. Static binding is faster and safer, since it resolves the binding question at compile-time, rather than run-time. Dynamic binding is more flexible, and is better able to support polymorphism, a fundamental OO principle.
An object-oriented language may provide either form of typing (static or dynamic) and either form of binding (static or dynamic), which makes four possibilities to consider. Traditionally, non-OO high level languages use static typing and static binding. Pure OO languages use dynamic typing and dynamic binding.