CSCE 3110 Data Structures & Algorithm Analysis Algorithm Analysis I Reading: Weiss, chap.2.
CSCE 3110 Data Structures & Algorithms
description
Transcript of CSCE 3110 Data Structures & Algorithms
CSCE 3110Data Structures &Algorithms
C++ warm-up
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructor, copy constructor, and assignment operatorConstTemplate
History of C++
1972: C language developed at Bell Labs
Dennis Ritchie wrote C for Unix OSNeeded C for work with Unix
late 70s: C becomes popular for OS development by many vendors
Many variants of the language developedANSI standard C in 1987-89
History of C++ (continued)
early 80s: Bjarne Stroustrup adds OO features to C creating C++90s: continued evolution of the language and its applications
preferred language for OS and low level programmingpopular language for application developmentlow level control and high level power
Conceptually what is C++
Alternatives:is it C, with lots more options and features?is it an OO programming language with C as its core?is it a development environment?
On most systems it is a development environment, language, and library, used for both procedural and object oriented programming, that can be customized and extended as desired
Versions of C++
ANSI C++Microsoft C++ (MS Visual C++ 6.0)Other vendors: Borland, Symantec, Turbo, …Many older versions (almost annual) including different version of C tooMany vendor specific versionsMany platform specific versionsFor this class: Unix / Linux based versions
g++
Characteristics of C++ as a Computer Language
ProceduralObject OrientedExtensible...
Other OO Languages
Smalltalkpure OO language developed at PARC
Java built on C/C++objects and data types
Eifel and others
What you can do with C++
Apps (standalone, Web apps, components)Active desktop (Dynamic HTML, incl Web)Create graphical appsData access (e-mail, files, ODBC)Integrate components w/ other languages
Disadvantages of C++Tends to be one of the less portable languagesComplicated?
40 operators, intricate precedence, pointers, etc.can control everythingmany exceptions and special casestremendous libraries both standard, vendor specific, and available for purchase, but all are intricate
Aspects above can result in high maintenance costs
Advantages of C++Available on most machinesCan get good performanceCan get small sizeCan manage memory effectivelyCan control everythingGood supply of programmersSuitable for almost any type of program (from systems programs to applications)
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Primitive Types
bool true or false (only C++)char 8/16-bit short 16-bit signed integerint 32-bit signed integerunsigned 32-bit unsigned integerlong 32 / 64-bit signed integerfloat 32-bit floating pointdouble 64-bit floating point
Operators and Precedence
[] . to access arrays elements / to access object methods and fields
expr++ expr-- ++expr --expr ! new (type)expr* / %+ - << >> (integers only)< > >= <=== !=&
Operators and Precedence
^|&& (booleans only)|| (booleans only)?:= += -= *= ….
C++ allows operator overloading
Precedence Example
What is: 5 + 21 / 4 % 3= 5 + (21 / 4) % 3= 5 + ( 5 % 3)= 5 + 2= 7
Explicit Casting
(type) expressionPossible among all integer and float typesPossible among some class references
E.g. int i = (int) ( (double)5 / (double)3 )
Implicit Casting
Applied automatically provided there is no loss of precision
float doubleint double
Exampleint iresult, i=3; double dresult, d=3.2;dresult = i/d => implicit casting dresult=0.9375iresult = i/d => error! Why? Loss in precision,
needs explicit casting
Control Flow
if (boolean)statement;
else if(boolean)statement2;
else statement3;
Booleans only, not integers!if (i > 0) correctif (i = 2) correct / incorrect ?
Switch / caseswitch (controlVar){ case 'a' :statement-1break; case 'b' :statement-2break; default :statement-3break; }Do not forget the break command to avoid surprise result!
Loopswhile(<boolean>) statement;
do statement;while(<boolean>)
for(init-expr; <boolean>; incr-expr) statement;
Loop Refresher
Which loops must execute their statements at least once?Which loops can choose to never execute their statements?Which value of the boolean indicates to do the statements again?
Some Conventions for Variable Names
Use letters and numbersDo not use special characters including spaces, dots, underlines, pound signs, etc.The first letter will be lower caseUse variable names that are meaningful (except for occasional counters that we might call i, j, x, etc.)You can concatenate words, and capitalize each after the first, e.g., bankBal, thisAcctNum, totAmtIf you abbreviate, be consistent. For example do not use both bankBal and totalBalance as variable names.
Some Conventions for Struct and Class Names
In creating names of structs and classes, apply the same rules as for variable names, except the first character will be upper caseExample:
an object's name: myCarthe struct or class name: Car
Another Example: aPerson and Person
Overview
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Passing ParametersC++ allows for three different ways of passing parameters:
Pass “by value”• E.g. foo (int n)• Appropriate for small objects (usually primitive types) that
should not be altered by the function callPass “by constant reference”
• E.g. foo(const T& myT)• Appropriate for large objects that should not be altered by the
function callPass “by reference”
• E.g. foo(bool & errFlag)• Appropriate for small objects that can be altered by the function
call• Array types are always passed “by reference”
Passing by value
void square(int i){ i = i*i;}int main(){ int i = 5; square(i); cout << i << endl;}
Passing by reference
void square(int& i){ i = i*i;}int main(){ int i = 5; square(i); cout << i << endl;}
Passing by constant reference
void square(const int& i){ i = i*i;}int main(){ int i = 5; square(i); cout << i << endl;}
Wont work, why?
Passing by constant reference
int square(const int& i){ return i*i;}int main(){ int i = 5; cout << square(i) << endl;}
Will t his work?
What is a reference?An alias – another name for an object.
int x = 5; int &y = x; // y is a // reference to x y = 10;
What happened to x?What happened to y? – y is x.
Why are they useful?
When passing argument of large size (class type), can save spaceSometimes need to change a value of an argumentCan be used to return more than one value (pass multiple parameters by reference)
How are references different from Pointers?
Reference Pointer
int a = 10; int b = 20; int &c = a; c = b;
What is the value of a?
int a = 10; int b = 20; int *c = &a; c = &b;
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Classes
Provide a mechanism for defining classes of objects.
We can define the class of all computers to have certain characteristics.An instance of a computer is your home PC.
Classes contain member variables and member functions.
Classes in C++:Why Create Classes / Objects?
Keeps all related info (i.e., data) togetherRefer to all the related info by one nameProtect the informationHide methods that use or change the infoKeep methods together with their related info
Example of Benefits of Creating an Object
Keeps all related info (i.e., data) togetherPerson thisPerson;Person thisPerson = new Person ("Bill", "Clinton",
52);Refer to all the related info by one name
thisPersonProtect the informationlastName = "Dole"; //normally data members are private, and member functions are public
Classes and ObjectsMammals
Humans Tigers
Hank Peggy Tony
class
classclass
inherits inherits
instance-ofinstance-of
Example of a Simple Classclass Change{private:
int quarters;int dimes;
public:int getQuarters() {return quarters;} int getDimes() {return dimes;}void setQuarters(int aQuarters) {quarters = aQuarters;}…...void printChange(){cout << "\nQuarters: " << quarters << " Dimes: " << dimes << endl;}
};
More Class Exampleclass human{
// this data is private to instances of the classint height;char name[];int weight;
public:void setHeight(int heightValue);int getHeight();
};
Function Definitionsvoid human::setHeight(int heightValue){
if (heightValue > 0)height = heightValue;
elseheight = 0;
}
int human::getHeight(){
return(height);}
Example// first we define the variables.int height = 72;int result = 0;human hank;
//set our human’s heighthank.setHeight(height);
//get his heightresult = hank.getHeight();
cout << “Hank is = “ << result << “inches tall” << endl;
Hank is 72 inches tall
Output
Instantiating an ObjectThe class definition does not create any objectsInstantiating and constructing are equivalent words for building a new object based on the model (i.e., template) of the classInstantiating is done just like declaring a variable of a built in data typeInstantiating is done by a constructor (sometimes called a constructor method)
If the "class provider" does not provide a constructor, then the C++ compiler provides a default one automaticallyThe default constructor does not provide values to the data members (i.e. the instance variables)
Instantiating an Object (more)
When the object is instantiated, memory is allocatedExample of instantiation (implicit call of constructor)
Car myCar;Elephant oneElephant, twoElephant;
No initialization takes placeEach object has its own memory allocation
oneElephant and twoElephant are separate objects in different locations in memoryEach is addressed individually by name or locationEach data member is addressed individually using the object name and the data member name, for example:
oneElephant.agetwoElephant.name
Referencing an Object
Each object has a name (or a location) which is assigned when the object is instantiatedprivate data members are accessible only within the class
since most data members are private, that means that these data items are accessed generally by means of member functionsmyElephant.age = 72; //won't work, assuming age //is declared as privatemyElephant.setAge(72); // will work
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Inheritance
The power of object-oriented languagesEnables reuse of fields/methods
All parent fields included in child instantiationProtected and public fields and methods directly accessible to childParent methods may be overriddenNew fields and methods may be added to the childMultiple inheritance
Inheritance (cont’d)
class classname: public parentname {private: ….;public:….;//access to parent methods through// parentname::methodname …
}
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Header file
For complex classes, the member functions are declared in a header file and the member functions are implemented in a separate file.
This allows people to look at the class definitions, and their member functions separately
The header file needs to be included in your program when you use the classes defined in the head file
#include “Segment.H”
#include <iostream>
#include
Insert header file at this point.
Use library header.
Header Guards
#ifndef __SEGMENT_HEADER__#define __SEGMENT_HEADER__
// contents of Segment.H//...
#endif
To ensure it is safe to include a file more than once.
Header Guards
#ifndef __SEGMENT_HEADER__#define __SEGMENT_HEADER__
// contents of segment.H//...
#endif
To ensure it is safe to include a file more than once.
If this variable is not defined…Define it.
End of guarded area.
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Output
#include<iostream>Tell compiler that we are doing I/O
coutObject to which we can send data.
<<operator for sending data.
endl `\n’ `\t’Special symbols that we can send.
Formatting Output
ios::left left justify the outputios::right right justify the outputios::scientific use scientific notation for numbersios::hex print numbers in hexadecimal baseios::dec print numbers in decimal baseios::uppercase print all characters in upper case
cout.setf(long flag) cout.unsetf(long flag)Set different formatting parameters for next output.
Disable these formatting parameters.
Example#include<iostream.h>main(){
cout.width(10); //sets width to 10cout << “hello” << endl;cout.setf(ios::left);cout << “hello” << endl;
cout << 16 << endl;cout.setf(ios::hex, ios::basefield);cout << 16 << endl;
}
hellohello1610
Output
Input
#include <iostream.h>Tell the linker we are doing basic I/O
cinThe input object. It retrieves input from the keyboard
>>The extractor operator.
Example
#include <iostream.h>
main (){
int userInput;cout << “Enter number:”;cin >> userInput;cout << “You entered ” <<
userInput << endl;}
Enter number:12345You entered 12345
Output
I/O From a File
I/O from a file is done in a similar way.#include <iostream.h>#include <fstream.h>main(){
int inputNumber;
ofstream myOutputFile(“outfile”);ifstream myInputFile(“infile”);myOutputFile << “text to file.” << endl;myInputFile >> inputNumber;myOutputFile.close();myInputFile.close();
}
#include <string>#include <fstream>#include <iostream>#include <iomanip>using namespace std;
int main(int argc, char *argv[]){ // Check input if(argc<2) { cout<<"Usage: "<<argv[0]<<" <filename>"<<endl; return 0; }
// Try to read from file cout<<"Reading tokens from file '"<<argv[1]<<"':"<<endl; ifstream in(argv[1]); if(!in) cout<<" - Could not read from file '"<<argv[1]<<"'."<<endl; else { string token; cout.setf(ios::right); for(unsigned i=1; in>>token; i++) cout<<setw(4)<<i<<": "<<token<<endl; } in.close(); cout<<endl;
// Allow user to enter a token string text; cout<<"Enter some text: "; getline(cin, text);
// Append new tokens to file ofstream out(argv[1], ios::app); if(out) out<<endl<<text<<endl; else cout<<"- Could not write to file '"<<argv[1]<<"'"<<endl; out.close();
return 0;}
This program reads a file name given by the user and the read token by token from the file. The tokens are printed to the standard output.
The second half of the algorithm reads a token from a standard input and appends it to the file that was given.
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
What is a pointer?
int x = 10;int *p;
p = &x;
p gets the address of x in memory.
p
x10
What is a pointer?
int x = 10;int *p;
p = &x;
*p = 20;
*p is the value at the address p.
p
x20
What is a pointer?
int x = 10;int *p;
p = &x;
*p = 20;
Declares a pointer to an integer
& is address operator gets address of x
* dereference operator gets value at p
A Pointer Exampleint main(){
int i, j;int *pi, *pj;
i = 5;j = i;pi = &i;pj = pi;*pj = 4;
cout << i << “ “;cout << j << “ “;cout << *pi << “ “;cout << *pj << endl;
return 0;}
> 4, 5, 4, 4
Allocating memory using new
Point *p = new Point(5, 5);Point is a class already definednew can be thought of a function with slightly strange syntaxnew allocates space to hold the object.new calls the object’s constructor.new returns a pointer to that object.
Memory Allocation Examplesnew returns a pointer to the dynamically created object.
#include “Cow.h” #include <iostream>using namespace std;
int main(){int *i = new int(12);Cow *c = new Cow;...delete i;delete c;
return 0;}
Problems
Dangling pointersPointers to memory that has already been deallocatedsegmentation fault (core dump)... or worse....
Memory leakLoosing pointers to dynamically allocated memorySubstantial problem in many commercial products
• See Windows 98C++ HAS NO GARBAGE COLLECTION!
Dangling pointer examples
int main(){int *myNum = new int(12);int *myOtherNum = myNum;
delete myNum;
cout << *myOtherNum << endl;
return 0;}
int* badFunction(){int num = 10;return #
}int* stillBad(int n){
n += 12;return &n;
}int main(){
int num = 12;int *myNum = badFunction();int *myOtherNum = stillBad(num);
cout << *myNum << “, “;cout << *myOtherNum << endl;
return 0;}
Memory Leak Examples
int main(){int *myNum = new int(12);myNum = new int(10);// Oops...
delete myNum;
return 0;}
int evilFunction(){int *i = new int(9);return *i;
}
int main(){int num = evilFunction();
// I’m loosing my memory!!
return 0;}
Deallocating memory using delete
// allocate memoryPoint *p = new Point(5, 5);
...// free the memorydelete p;
For every call to new, there must beexactly one call to delete.
Using new with arrays
int x = 10;int* nums1 = new int[10]; // okint* nums2 = new int[x]; // ok
Initializes an array of 10 integers on the heap.C++ equivalent of Cint* nums = (int*)malloc(x * sizeof(int));
Using new with multidimensional arrays
int x = 3, y = 4;int* nums3 = new int[x][4][5];// okint* nums4 = new int[x][y][5];// BAD!
Initializes a multidimensional arrayOnly the first dimension can be a variable. The rest must be constants.Use single dimension arrays to fake multidimensional ones
Using delete on arrays
// allocate memoryint* nums1 = new int[10];int* nums3 = new int[x][4][5];
...// free the memorydelete[] nums1;delete[] nums3;
Have to use delete[].
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Class Destructors
If a class dynamically allocates memory, we need a way to deallocate it when it’s destroyed.Distructors called upon distruction of an object
class MyClass{public:
MyClass(){// Constructor
}~MyClass(){
// Destructor}
...};
Destructors
delete calls the object’s destructor.delete frees space occupied by the object.
A destructor cleans up after the object.Releases resources such as memory.
Destructors – an Example
class Segment{public: Segment(); virtual ~Segment();private: Point *m_p0, *m_p1;};
Destructors – an Example
Segment::Segment(){ m_p0 = new Point(0, 0); m_p1 = new Point(1, 1);}Segment::~Segment(){ delete m_p0; delete m_p1;}
Copy Constructor and Assignment Operator
Copy Constructor: class Rooster{public:
...Rooster(const Rooster &rhs){
// Do your deep copy}...
};...// UsageRooster r(12);Rooster s(r);
Assignment Operator:class Rooster{public:
...Rooster& operator=(const Rooster
&rhs){ // Copy stuff
}...
};...// UsageRooster r(12), s(10);r = s;
Canonical Form
All classes should have each of the following:
Default constructorCopy constructorAssignment operatorDestructor
// Canonical Cowclass Cow{public:
Cow(){...}Cow(const Cow &rhs){...}Cow& operator=(const Cow &c)
{...}~Cow(){...}
...};
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructore, copy constructor, and assignment operatorConstTemplate
Introducing: const
void Math::printSquare(const int& i){ i = i*i; cout << i << endl;}int main(){ int i = 5; Math::printSquare(i); Math::printCube(i);}
Won’t compile.
How does const work here?void Math::printSquares(const int& j, int& k){
k = k*k; // Does this compile? cout << j*j << “, “ << k << endl;}int main(){ int i = 5; Math::printSquares(i, i);}
Returning const references is OK
class Point{point: const double& getX() const; const double& getY() const; void move(double dx, double dy);private: double m_x, m_y;}
const double& Point::getX() const{ return m_x;}
Constant function, also called accessor
Return a reference to a constant double
Namespaces
Namespaces are kind of like packages in JavaReduces naming conflictsMost standards C++ routines and classes and under the std namespace
using namespace#include <iostream>...std::string question =
“How do I prevent RSI?”;std::cout << question << std::endl;
using namespace std;
string answer = “Type less.”;cout << answer << endl;
But, not in header files!
Outline
History and overviewBasic featuresParameter passingClassesInheritance and virtualHeader fileIOMemory ManagementBig three: destructor, copy constructor, and assignment operatorConstTemplate
Template
What exactly are templates for, and why learn them?
• Limited Generic Programming (polymorphism)Some functions have the same semantic meaning for some (if not all) data types. For instance, a function print() should display a sensible
representation of anything passed in. Ideally, it shouldn’t need to be rewritten for each possible type.
• Less repetitive codeCode that only differs in the data type it handles does not have to berewritten for each and every data type you want to handle. It’s easier toread and maintain since one piece of code is used for everything
Example: a swap function
Naive method – write an overloaded function for each type
void swap(int &a, int &b) { int c = a; a = b; b = c;}
void swap(T &a, T &b) { T c = a; a = b; b = c;}
Swap for integers Swap for an arbitrary type T
template <typename T>void swap(T &a, T &b) { T c = a; a = b; b = c;}
This function can be used with any type that supports assignment and can be passed in as a non-const reference.
Problem: Oftentimes, it is nice to be able to swap the values of two variables. This function’s behavior is similar for all data types. Templated
functions let you do that – in most cases without any syntax changes.
Template method – write one templated function
Template Syntax: swap dissected
template <typename T>void swap(T &a, T &b) { T c = a; a = b; b = c;}
The template<…> line states that everything in the following declaration or definition is under the subject of the template. (In this case, the definition is the function swap)
In here goes a list of “placeholders variables.” In almost all cases, they will be specified with either the typename or class keywords. These two keywords are equivalent.
“Placeholder variables” have one value within each template declaration. Think of them as being replaced by whatever type you specify the template to be.
Template Syntax: Using it
template <typename T>void swap(T &a, T &b) { T c = a; a = b; b = c;}
Example: double d1 = 4.5, d2 = 6.7;
swap(d1, d2);
Syntax
Class Templates: Example
Example: A templated, dynamic, 2 dimensional array (Matrix)*#ifndef MATRIX_H#define MATRIX_H
template <typename T>class Matrix {public: Matrix(int rows, int cols); Matrix(const Matrix &other); virtual ~Matrix();
Matrix& operator=(const Matrix &rhs); T* operator[](int i); int getRows() const; int getCols() const;
protected: void copy(const Matrix &other);
private: Matrix(); int m_rows; int m_cols; T *m_linArray;};
#endif /* MATRIX_H */File: Matrix.h
Notice the only addition to the class definition is the line: template <typename T>
Within the the definition block, the placeholder has can be used as a data type. When the template is specialized, it takes on the value of the specialization.
template <typename T>T* Matrix<T>::operator[](int i) { return m_linArray + (i*m_cols);}
template <typename T>void Matrix<T>::copy(const Matrix &other) { m_rows = other.m_rows; m_cols = other.m_cols;
int size = m_rows * m_cols; m_linArray = new T[size]; for( int i=0; i < size; i++ ) { m_linArray[i] =
other.m_linArray[i]; }}
template <typename T>int Matrix<T>::getRows() const { return m_rows;}
template <typename T>int Matrix<T>::getCols() const { return m_cols;}
Class Templates: Example cont’d#include "Matrix.h"
template <typename T>Matrix<T>::Matrix(){}
template <typename T>Matrix<T>::Matrix(int rows, int cols) { m_rows = rows; m_cols = cols; m_linArray = new T[m_rows * m_cols];}
template <typename T>Matrix<T>::Matrix(const Matrix &other) { copy(other);}
template <typename T>Matrix<T>::~Matrix() { delete[] m_linArray;}
template <typename T>Matrix<T>& Matrix<T>::operator=(const Matrix &other) { if( this != &other ) { delete[] m_linArray; copy(other); }
return *this;} File: Matrix.cc
template <typename T>Matrix<T>& Matrix<T>::operator=(const Matrix &other) { if( this != &other ) { this->~Matrix(); copy(other); }
return *this;}
Class Templates: Member Functions Dissected
Again, a templated class name by itself has no meaning (eg. Matrix by itself means nothing). It only gets meaning through specialization, explicit or implicit. Thus, when referring to an instance of a templated class (a specific specialization), the class name must be explicitly specialized.
Here, the template has been implicitly specialized by its context. It is within the specialization region of the class scope. Thus it does not need the template arguments. For a class definition, the specialization region is the class block.
specialization region of Matrix<T>::
Notice that the specialization region does not include the return type. Thus the return type needs explicit specialization
This may be obvious, but remember that though constructors and destructors have the same name as a the class template, they are functions and do not need to be specialized.
Class Templates: usage
• Templated classes must be explicitly specialized. Thus, to create a 2 dimensional Matrix of doubles using the last example, the syntax would be: Matrix<double> m(3,3);
Syntax
STL
Allows you to easily store anything without writing a container yourselfWill give you the most hideous compile errors ever if you use them incorrectly.
STL example
using namespace std;typedef list<int> intlist;typedef intlist::iterator intlistIter;
intlist v;v.push_back(4);intlistIter a;for(a = v.begin(); a != v.end(); ++a){
int c = (*a);}
Now compile and run a simple c++ program
Compilation ModelPreprocessor
Resolves all preprocessor directives#include, #define macros, #ifdef, etc.
CompilerConverts text into object filesMay have unresolved interobject references
LinkerResolves all interobject references (or gives you a linker error)Creates the binary executable
LoaderLoads the program into RAM and runs the main() function
Compilation
PreprocessorInlines #includes etc.
CompilerTranslates to machine code
Associates calls with functions
LinkerAssociates functions with definitions
Object files
Executable
External Libraries, libc.so, libcs123.so
HelloWorld.cpp
#include <iostream> // For coutusing namespace std;
int main(){ cout << "Hello World!" << endl;
return 0;}
Compiling with g++
ix$ lshello.cppix$ ls hello.cppix$ g++ hello.cpp ix$ lsa.out* hello.cppix$ g++ -c hello.cppix$ lsa.out* hello.cpp hello.oix$ g++ -o hello hello.cpp ix$ ./hello Hello World!
makefile
> make
Simple makefile
All: hellohello: hello.o g++ -o hello hello.ohello.o: hello.cpp g++ -c hello.cpp
ix$ lshello.cpp makefileix$ makeg++ -c hello.cppg++ -o hello hello.oix$ lshello* hello.cpp hello.o makefileix$ ./hello Hello World!