250 likes | 269 Views
CSC 143. Modules: Specification, Implementation, and C/C++ Source Files [Chapter 1]. Modularization. Basic idea: break apart large system into smaller units (modules) Group related functionality in one module Often continued in a hierarchy of modules
E N D
CSC 143 Modules: Specification, Implementation, and C/C++ Source Files [Chapter 1]
Modularization • Basic idea: break apart large system into smaller units (modules) • Group related functionality in one module • Often continued in a hierarchy of modules • Design modules to be general and reusable • Multiple times in same program • Different programs/programmers
Specification vs. Implementation Two parts of each module • Specification (what) • Also known as “interface” • Describes the services that the module provides to clients (users) • Publicly visible • Implementation (how) • Parts of the module that actually do work • Private, hidden behind module interface
Specification as Contract Module specification acts as a contract between client and implementor • Client depends on specification not changing • Doesn’t need to know any details of how module works, just what it does • Implementor can change anything not in the specification, (eg. to improve performance) • Implementation is a “black box” (encapsulation), providing information hiding
Locality • Locality of design decisions from encapsulation • Benefits of private data and algorithm locality: • Division of labor • Easier to understand • Implementation independence
Specification • Supplies constants, data types, function prototypes • Comments describing what each function does • Preconditions: What should be true before function call (e.g., relationships among arguments) • Postconditions: What is true after function return (e.g., relationship of return value to arguments) • Invariants: What must be true while function executes (e.g., relationships among local variables)
Modules in C++ • Modules represented by a pair of files • specification (.h) file • implementation (.cpp, .cc, .c++, .C, etc) file • Client’s only interaction with module is through the interface defined in the .h file
Imports and Exports • Specification (.h) file declares which items are exported • constants, function prototypes, and data types • Client program must import features of a module to use them • Use the #include directive
Sample Specification File // Specification file for computational geometry // functions // POST: returns the area of a circle with given // radius double circleArea (double radius); // PRE: area must be non-negative // POST: returns the radius of a circle of given // area double circleRadius(double area); prototype geometry.h
Sample Implementation File // Implementation of geometry functions #include "geometry.h" #include <math.h> const double PI = 3.1415; double circleArea (double radius) { • return PI * radius * radius; } double circleRadius (double area) { return sqrt(area/PI); } geometry.cpp
Sample Client File #include <iostream.h> #include "geometry.h" int main(void) { • double value; • cout << "Enter radius: "; • cin >> value; • cout << "Area of circle is " << • circleArea(value) << endl; • return 0; } main.cpp
Separate Compilation • One module usable by many clients • Individual modules may be changed and recompiled without changing entire program • Client’s code can be changed and recompiled without recompiling modules • Note: Interface (specification) changes mandate recompiling both implementation and client
Designing Modules • Must think about implementor’s and client’s roles • Implementor’s goals: • Provide a reusable, robust abstractions • Make interface independent of client • Keep freedom to modify implementation • Protect module from abuse and misuse • Client’s goals: • Assemble a program from usable modules • Rely solely on specification
Standard Libraries • C/C++ comes with some (C++ many) predefined modules (libraries) • iostream.h, fstream.h for stream I/O • math.h for sin, cos, sqrt, etc. • string.h for strcmp, strlen, etc. • C++ comes with the standard template library • If there is a choice, prefer the STL to the older C modules • Compilers also include nonstandard libraries • Graphics, windowing, etc. • Please don’t use them for CSC 143
.h or not .h? (1) • <iostream.h>: part of the old standard library • <iostream>: part of the latest standard library • The latest C++ standard library is big (well huge, well very huge…) • To avoid name conflicts with code written by users of the standard library (=everybody), all standard library functions live in a namespace called std.
.h or not .h? (2) • What are our options? • #include <iostream.h>cout << "Using the old library"; • #include <iostream>std::cout << "Using the new library" • #include <iostream>using namespace std; //name conflicts are unlikely //in our small programscout << "Using the new library"; • Officially the old library is no longer supported • Some functions are available only in the new library (e.g. <string>) • Don't mix the old and the new
What about C header files? • With the old library, write • #include <stdlib.h> • With the new library, write • #include <cstdlib> • Rule: when using the new library, to include a C header file, add a c at the beginning of the name, remove .h at the end of the name.
Definition vs Declaration • In C++ (and C) there is a careful distinction between defining and declaring an item. • Definition: The C++ construct that actually creates the item. (ex. full function w/body) • Declaration: A specification that gives the information needed to use an item (ex. function prototype)
Definition vs Declaration (2) • Rule: Every item must have exactly one unique definition among the files that make up the program. • An item may be declared as often as needed (but only once within a file). • Corollaries: • Specification (.h) files should contain declarations • Definitions belong in a single .cpp file • The implementation file should #include the corresponding specification file for consistency checking.
Program Files // hello.h // write hello // followed // by the value of i void hello(int i); // main.cpp # include “hello.h” int main(void) { hello(1); hello(2); return 1; } // hello.cpp # include “hello.h” # include <iostream.h> // write hello ... void hello (int i) { cout << “Hello ”; cout << i << endl; } Specification Implementation Client
Building the Program Three stages to go from source code to executable: • Preprocess • read#include files, expand #define • Compile • Convert C++ code to object code (machine language) the computer can execute directly • Link • Connects your object code with system libraries to make an executable program
Building the Program (2) compiler iostream.h math.h compiler geometry.h geometry.h geometry.cpp main.cpp linker Compile geometry.obj Compile main.obj geometry.obj Link main.exe main.obj libraries
Separate Compilation • Each module’s .cpp source code is converted into object code separately • Linker collects object code together to build executable • Many environments hide this process from you • On MSVC, just press the “build all” button (or even just “run” …) • Must be done “manually” under UNIX (but mechanisms exist to make it easier: e.g., make)
Multiple Inclusion Problem ... const int MINSIZE = 20; void writeLetters (ofstream& otfile); ... lmatrix.h #include "lmatrix.h" ... word.h #include "lmatrix.h" #include "word.h" ... main.cpp Compile-time error if identifiers (function names, constants, etc.) are defined multiple times:
Multiple Inclusion Preprocessor directive • To avoid this problem, use preprocessor directives: // lmatrix.h #ifndef LMATRIX_H #define LMATRIX_H ... const int MINSIZE = 20; void writeLetters (ofstream& otfile); ... #endif • Read the above as: • If LMATRIX_H undefined, compile the code through • #endif