0% found this document useful (0 votes)
10 views33 pages

CS3505 Lecture4

The document covers key concepts in C++ programming, focusing on destructors, header files, makefiles, and libraries. It discusses the importance of organizing code into multiple files, using include guards, and creating makefiles for efficient compilation. Additionally, it introduces design patterns, particularly the Façade pattern, and presents an assignment related to creating a façade for a C-style PDF creation library.

Uploaded by

liang19880404
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views33 pages

CS3505 Lecture4

The document covers key concepts in C++ programming, focusing on destructors, header files, makefiles, and libraries. It discusses the importance of organizing code into multiple files, using include guards, and creating makefiles for efficient compilation. Additionally, it introduces design patterns, particularly the Façade pattern, and presents an assignment related to creating a façade for a C-style PDF creation library.

Uploaded by

liang19880404
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

CS 3505: Software Practice II

Lecture 4:
Headers, Makefiles, and Libraries
Assignment Questions?
Back to the Point class
Destructors
• Destructors are called when an object leaves
scope or delete is called on an object.
• Looks like
~Point() { stuff }
• Destructors are needed when the class has
acquired resources that need to be cleaned
up
– memory
– open files/network connections/etc.
• Does Point need a destructor?
Using Multiple Files
• Most C++ projects are broken into multiple
files
– Often move each class into its own file(s)
• An implementation in a .cpp file
• An interface in a header file with a .h extension
– The header file is #include’d in .cpp files
• This is a very simple model
• During compilation, the .h text is (virtually) inserted
into the .cpp file at the location of the include
• Break point.cpp into multiple files.
#include
• #include is an example of a preprocessor directive – it
tells the compiler to do something
• Two main ways of including
– #include <systemheader>
• searches in known locations for systemheader
– #include “myLocal.h”
• looks in local directory and project specified locations
• Why not systemheader.h?
– C-style headers are <stdio.h>
– C++-style lack the .h to be different
• there is a file called “systemheader” on our system
Design Rules for .h files
• Definition in Ex.h
class Ex {
int x; // data member
public:
Ex(int x); // constructor
};
No implementation, just forward declaration
• Implementation of constructor in Ex.cpp
Ex::Ex(int x) : x(x) {
}

Class name :: Name of function (happens to be Ex)


Redefinition Issues
• Easy to include a .h A.h
more than once some A code
• This will cause a B.h
redefinition error of #include A.h
the class or functions B code
or variables
main.cpp
• Use an include guard
#include “A.h”
– a conditional
preprocessor directive #include “B.h”
– set a preprocessor
variable
Design Rules for .h files
• Use include guards
#ifndef EX_H
#define EX_H
class Ex { Define a preprocessor
int x_; macro – it can act like
public: a variable. Here, just
Ex(int x); its existence is used.
};
#endif
Design Rules for .h files
• The header should be independently legal
– It should compile if included in an empty .cpp
#include “ex.h”
• Use the header first in the matching .cpp
#include “ex.h”
#include <iostream>
using namespace std;
Ex::Ex(int x) : x_(x) {
}
Design Rules for .h files
• No ‘using namespace’ in .h

class Ex {
int x_;
public:
Ex(int x);
Ex(std::ostream);
};
This means we will give full name
Design Rules for .h files
• Use minimal includes in the header
#include <iostream>
class Ex {
int x_;
public:
Ex(int x);
Ex(std::ostream);
};
Design Rules for .h files
• The implementation .cpp should not
assume the .h will continue to have
includes such as <iostream>
#include <iostream> #include “Ex.h”
class Ex { #include <iostream>
int x_;
public: Ex::Ex(int x) : x_(x) {
Ex(int x); }
};
g++ Compilation
• g++ really does two things.
– Compile the source
– Link the files together
• If Point(x,y) is defined in point.cpp, then when
main.cpp is compiled it
– Sees the prototype of Point(x,y) in the .h file
– Enters that in some internal table
– When it is used in main.cpp it knows it should exist
– During linking, it makes the connection between the
prototype table and the actual compiled implementation
Object Files
• You can compile without linking

g++ -c point.cpp

• This makes an object file point.o, which


is the compiled code ready for linking.
Compilation of Multi-File Projects
• Will quickly get unwieldy
g++ -o point main.cpp point.cpp
Or
g++ -o point main.o point.o

• Make
– A system for compiling projects
– Uses a Makefile to define compilation rules
– Speeds compilation by only redoing ‘touched’
files.
Makefiles
• Basic Makefile setup
“Thing to make”: “what it depends on”
“How to make it”
• A simple Makefile for point is
– Note that the .h is in the dependencies but not
in the compilation line – the .cpp code
includes it
point: main.cpp point.h point.cpp
g++ -o point main.cpp point.cpp
• Type ‘make’ or ‘make point’ to compile
More Advanced
• Define compilation properties with
variables

# use variables to define compilation


# properties
CC = g++
CFLAGS = -Wall
More Advanced
• Define rules for executable and for each
source file
– only recompiles changed .cpp files

point: main.o point.o


$(CC) $(CFLAGS) -o point main.o point.o
main.o: main.cpp point.h
$(CC) $(CFLAGS) -c main.cpp
point.o: point.cpp point.h
$(CC) $(CFLAGS) -c point.cpp
More Advanced
• Add a ‘clean’ rule
– sometimes you want to make sure everything
gets recompiled.
clean:
rm –f point *.o

• A ‘test’ rule can be handy


test:
./point > testLog.txt
Reorganizing the code
• Often want include files in one folder and
.cpp in another and executable source in
another.
point/
include/
point.h
src/
point.cpp main.cpp
Tell Compiler Where Things Are
• Define INCLUDE variable
INCLUDE = ../include
• Use –I flag to tell compiler to look in that
directory
• Use INCLUDE to point to .h file
main.o: main.cpp $(INCLUDE)/point.h
$(CC) $(CFLAGS) -I$(INCLUDE) -c main.cpp

The top INCLUDE is a dependency check if the .h has


changed. The bottom one is telling the compiler where to look
for include files.
Redone Makefile
CC = g++
CFLAGS = -Wall
INCLUDE = ../include
point: main.o point.o
$(CC) $(CFLAGS) -o point main.o point.o
main.o: main.cpp $(INCLUDE)/point.h
$(CC) $(CFLAGS) -I$(INCLUDE) -c main.cpp
point.o: point.cpp $(INCLUDE)/point.h
$(CC) $(CFLAGS) -I$(INCLUDE) -c point.cpp
clean:
rm -f point *.o
What to do with all the .o files
• Turn .o into a library
– Share code with headers and .a or .so library
files
• .a for static library
• .so for shared, dynamically-loaded library
• To make a library
– Archive command ‘ar’
libpoint.a : point.o
ar -rcs libpoint.a point.o
Using a Static Library
• Need 3 things
– When compiling the .cpp -> .o files
• Path to the header files (INCLUDE part)
– When linking the .o and .a -> executable
• Path to the .a file -L
• Name of the .a file -lname or just libname.a
– -l adds back in the lib and .a
• libraries go on the end of build line
point: main.o point.o libpoint.a
$(CC) $(CFLAGS) -L$(POINTLIBDIR) -o point
main.o -l$(POINTLIBNAME)
Design Patterns
• What are design patterns?
– not code reuse
• not a library – a pattern needs recoding for each
new context
– solution strategy/architecture reuse
– point out some subtle problems and provide a
potential solution
Levels of Reuse

Frameworks - .Net, Qt, Android

Design Patterns

Toolkits (libraries)

Idioms – Example: Include Guards

Languages
Gang of Four (GoF)
• Design Patterns book
launched this concept
for software
– borrowed from the
“patterns” idea in
architecture
– 4 authors
Façade Design Pattern
• façade
– an outward appearance that is maintained to
conceal a less pleasant or creditable reality.
• Problem: external code may be difficult to
use and end up tightly-coupled to yours.
• Solution: wrap a subset of the external
library in an easier-to-use interface
Façade Example: Initial Interface
class Light {
public:
void on() { std::cout << "Lights on" << std::endl; }
void off() { std::cout << "Lights off" << std::endl; }
};

class TV {
public:
void on() { std::cout << "TV on" << std::endl; }
void off() { std::cout << "TV off" << std::endl; }
};
The Façade
class houseControlFacade {
public:
Light hall,kitchen;
TV basement, main, porch, bathroom;

void on() { hall.on(); main.on(); }


void off() { hall.off(); main.off(); }
};
Discussion
• Why not just redo the interface?
– maybe not your code
– maybe you want to allow access to small subset but
not mess up main interface
• Doesn’t this intermediate layer just add more
locations for bugs?
– yes
– but may make a workable solution available to more
people
– allows changing the external lib and just changing the
facade
Assignment 2
• Make a façade for a C-style pdf-creation
library
• Add a small class to compute a shape
• Make an application that ties the two
together to make text follow the shape in a
pdf.

You might also like