separate compilation. a key concept in programming two kinds of languages, compilation (c, pascal,...
Post on 16-Jan-2016
225 Views
Preview:
TRANSCRIPT
Separate Compilation
A key concept in programming
Two kinds of languages, compilation (C, Pascal, …) and interpretation (Lisp, …, Matlab, Phython, Javascript…)
It was a ‘milestone’ for procedural programming, some old ones like Pascal cannot, …
It is in fact a kind of ‘abstract data type’, to separate the function “implementations” from its “definitions”
It is also impossible for large projet without it
Translating a Library
3
Program Source File
Library Header File
Library Implementation File
C++ Compiler
C++ Compiler
Linker
Program Object File
Library Object File
Program Executable File
g++ -c
g++ -c
.o
.o e.g., g++ foo.cpp bar.o fb.o
Motivation#include <iostream>using namespace std;
bool even(int);
bool odd(int x){
bool res;if(x == 0) res=false;else even(x-1);return res;
}
bool even(int x) { bool res;if (x == 0) res=true;else odd(x-1); return res;
}
int main(){
int x;cin >> x;cout >> odd(x) >> endl;cout >> even(x) >> endl;return 0;
}
#include <iostream>using namespace std;
bool even(int);bool odd(int);
int main(){
int x;cin >> x;cout >> odd(x) >> endl;cout >> even(x) >> endl;return 0;
}
bool odd(int x){
bool res;if(x == 0) res=false;else even(x-1);return res;
}
bool even(int x) { bool res;if (x == 0) res=true;else odd(x-1); return res;
}
It’s about ‘Organization’, organization of files!
One file many files …
3 functions: odd() even()main()“main.cpp”
odd()“odd.cpp”
even()“even.cpp”
main()“main.cpp”
Reasons:1. Reuse code for other programs2. Divide work among programmers3. Better maintenance, localize changes
#include <iostream>using namespace std;
bool odd(int);bool even(int);
int main(){
int x;while (cin >> x){
num_calls = 0;cout << boolalpha << odd(x) << endl;
}return 0;
}
main()“main.cpp”
#include <iostream>using namespace std;
bool odd(int);
bool even(int x){
…}
#include <iostream>using namespace std;
bool even(int);
bool odd(int x){
…}
even()“even.cpp”
odd()“odd.cpp”
g++ -c main.cpp main.o g++ -c even.cpp even.o g++ -c odd.cpp odd.o g++ -o odd-even main.o even.o odd.o odd-even
-c generates an object file -o generates an executable by linking all object files
g++ file.cpp a.out
Separate compilation by ‘makefile’
If only “main.cpp” is modified, just need to re-compile “main.cpp” and re-link by:g++ -c main.cppg++ -o odd-even main.o even.o odd.o
No need to re-compile the object files, i.e. even.o and odd.o
‘makefile’ will automate all these things!!!
‘makefile’ is also a program in ‘script’ language that organizes your ‘command files’!
Using header files
We do not want to repeat writing the same declarations in multiple files.
Should a declaration require updating, one has to go through all files that have the declaration and make the change.
More importantly, maintaining duplicate information in multiple files is error-prone.
Many declarations are repeated in “odd.cpp” and “even.cpp”, but
#include preprocessor directive
include header files Instructs C++ preprocessor to replace directive with a copy of the
contents of the specified file
Quotes for user-defined header files Preprocessor first looks in current directory If the file is not found, looks in C++ Standard Library directory
Angle brackets for C++ Standard Library Preprocessor looks only in C++ Standard Library directory #include <iostream>
11
#include <iostream>using namespace std;bool even(int);bool odd(int x)
#include “myInclude.h”bool odd(int x){
bool res;if(x == 0) res=false;else even(x-1);return res;
}
#include “myInclude.h”int main(){
int x;cin >> x;cout >> odd(x) >> endl;cout >> even(x) >>
endl;return 0;
}
#include “myInclude.h”bool even(int x) {
bool res;if (x == 0) res=true;else odd(x-1); return res;
}
myInclude.h main.cpp odd.cpp even.cpp
Example of headfile
Avoiding recursive inclusions … It is ok to have multiple declarations of a function prototype,
but not for its definition In the .h file, put the prototypes there .h files are likely to be multiply-included
In creating the .o file, there may be nested #include statement The nested #include statement may be recursive
In main.cpp, #include “foo.h” In foo.h, #include “bar.h” In bar.h, #include “foo.h”
To break the infinite “recursive” inclusion, use #ifndefine #define to define a “variable” in the compilation process of .o file
If a variable has been defined, the compiler will skip the code segment between #ifndefine and #endif.
13
#define preprocessor directive if XYZ is undefined, we process the file. Otherwise we do
not process the file (jumping to the #endif). XYZ should not appear in any other files.
14
#ifndef XYZ#define XYZ
f1();f2();…
#endif
File scope: external/internalEach file must know the existence of every variable, constant and function that it uses!
Global constants: repeat their definitions(global constants are ‘local’ to the file, internal!)
External (global) variables: add keyword “extern”
External functions: add function prototypes (with or without “extern”)
“extern” it’s (just) a declaration, but not a definition!equivalently, it means the variable / function is global and is definedin another file.
16
#include <iostream>#include "library.h"using namespace std;int Int=99;
int main(){ cout << "Hello"<<endl; cout << f(100) << endl; return 0;}
#include "library.h"
int f(int i){ return (Int + i);}
main.cppsource.cpp
Output:Hello199
library.hextern int Int;
int f(int);
Separate compilation with classes
Interface and Implementation
In C++ it is more common to separate the class interface from its implementation.
Abstract data type
The interface lists the class and its members (data and functions).
The implementation provides implementations of the functions.
18
What to do?
How to do?
19
Class interface header file *.h
Class implementation source code file *.cpp
Client/application/user driver file main.cpp
The implementation is hidden from the users!
Separate Files
.cpp source-code files .h header files
Separate files in which class definitions are placed Allow compiler to recognize the classes when used elsewhere Generally have .h filename extensions
Driver files Program used to test software (such as classes) Contains a main function so it can be executed
20
Class Libraries
21
Class declarations placed in header file Given .h extension Contains data items and prototypes
Implementation file Same prefix name as header file Given .cpp extension
Programs which use this class library called client programs
Example
The interface, implementation and driver separated into three files Interface contains data members and member function prototypes only Note the #ifndef statements to prevent multiple inclusions
22
#ifndef GRADEBOOK_H #define GRADEBOOK_H
class GradeBook{public: GradeBook( string ); void setCourseName( string ); string getCourseName(); void displayMessage();
private: string courseName;};
#endif
Gradebook6.h (with Validity Checking)
set functions perform validity checking to keep courseName in a consistent state
GradeBook implementation is placed in a separate file Include the header file to access the class name GradeBook Binary scope resolution operator :: “ties” a function to its class
23
#include "GradeBook6.h" // include definition of class GradeBook
void GradeBook::setCourseName( string name ){ // if name has 25 or fewer characters if ( name.length() <= 25 ) courseName = name;
// if name has more than 25 characters if ( name.length() > 25 ) { // set courseName to first 25 characters of parameter name courseName = name.substr( 0, 25 );
cout << "Name \"" << name << "\" exceeds maximum length (25).\n" << "Limiting courseName to first 25 characters."; }}
Gradebook6.cpp
Include the header file to use the class GradeBook
24
#include "GradeBook6.h" // include definition of class GradeBook
int main(){ // initial course name of gradeBook1 is too long GradeBook gradeBook1( "COMP104 Introduction to Programming in C++" ); GradeBook gradeBook2( "COMP152 OOP and Data Structures" ); cout << "gradeBook1's initial course name is: " << gradeBook1.getCourseName() << "\ngradeBook2's initial course name is: " << gradeBook2.getCourseName() << endl;
driver6.cpp (1/2)
Call set function to perform validity checking directly In Linux, compile them all together using g++ Gradebook6.cpp driver6.cpp Or using object files: g++ -c Gradebook6.cpp; g++ -c driver6.cpp; g++ driver6.o driver6.o
25
// modify myGradeBook's courseName (with a valid-length string) gradeBook1.setCourseName( "COMP104 C++ Programming" );
// display each GradeBook's courseName cout << "\ngradeBook1's course name is: " << gradeBook1.getCourseName() << "\ngradeBook2's course name is: " << gradeBook2.getCourseName() << endl; return 0;}
driver6.cpp (2/2)
26
Name "COMP104 Introduction to Programming in C++" exceeds maximum length (25).Limiting courseName to first 25 characters.gradeBook1's initial course name is: COMP104 Introduction to PgradeBook2's initial course name is: COMP152 OOP and Data StrugradeBook1's course name is: COMP104 C++ ProgramminggradeBook2's course name is: COMP152 OOP and Data Stru
driver6.cpp Sample Output
top related