COMP345:
Advanced Program Design with C++
Lecture 1
Department of Computer Science and Software Engineering Concordia University
Contents
1. C++ program structure
Free function and main function
2. Component and compilation unit header file and compilation file
3. Namespaces
Structure of C++ programs
C++ is a superset of C
Main function is the program driver Free functions
Data structures
A C program is a valid C++ program
Classes encapsulate other functions: Object-oriented
The main function is a free function, not a class member
Simple C++ program
Some compilers will allow you to omit the int or replace it with void
ends the invocation of main and return 0 as the functions value. This statement is not required
Program structure: multiple files programs
Only simplistic programs are self-contained into one file
C++ is a language that specifies programming structures and includes only
basic data structures and operators
Most programs require the use of libraries
Complier will compile the librarys code and the programs code, then the linker will link them
Unlike Java, a single C++ file can contain many classes/functions/data structures.
This leads to what is called physical design, i.e. decisions as to what entities are grouped within/across files.
Program structure: multiple files programs
Aside from having to use libraries, large programs need to be split into different files for various reasons:
Speed up compilation: Upon changes to the code, the compiler will recompile only the files that had a change.
Increase organization, decrease browsing time: Physically splitting your code along logical lines will make it easier to browse through the code to locate classes, functions, etc.
Facilitate code reuse: Modular physical design allows for grouping related entities and separating them from less related ones. Each group can then be logically designed to be reusable across different projects. Reused code can be fixed, fixing all projects that use it.
Split coding responsibilities among programmers: For really large projects, several programmers are involved. The larger are the program files, the more likely it is that several programmers are changing the same file simultaneously.
Contents
1. C++ program structure
2. Component and compilation unit
header file and compilation file 3. Namespaces
4. Basic terms & concepts
Program structure: compilation unit
In C++, a compilation unit is a file (.cpp)
A file may contain several functions, data
structures, or classes (unlike Java)
Each compilation unit is compiled individually into an object file
The object files typically have cross- references to other object files
The linker then attempts to resolve cross- references between the object files to form the unique executable file
Handle some textual manipulation before the text is given to the compiler (looks at directive #)
e.g. provides the ability for the inclusion of header files, macro expansions, conditional compilation, and line control.
Compilation unit and linkage: Example
file: one.h
class A {
int Af(int);
}
int onef(int);
file: one.cpp
#include one.h #include two.h int A::Af(int){
B myB;
myB.Bf();
}
int onef()int{
}
file: one.o
A::Af
B.Bf()
onef()
compile unit one.cpp
file: two.h
class B { int Bf();
}
class C{
}
file: two.cpp
#include two.h int B::Bf(){
}
file: two.o
B::Bf
compile unit two.cpp
Program structure: compilation units as program parts
Compilation units are separate program parts, or components
Kept in separate files
Compiled separately and linked together before the program runs
Compared to Java, C++ provides much more freedom to define what is a part, as it can be composed of a group of functions, data structures and classes
There is no such thing as Java-like packages in C++.
In C++, there is a separation between the interface and the
implementation of a component
Each component is a group of highly cohesive and highly coupled elements
Program structure: cohesion
Cohesion: The degree to which the elements of a module belong together in the achievement of a common goal.
Cohesion is increased if:
The functionalities embedded in a module have much in common.
The composing elements carry out a small number of related activities, by avoiding coarsely grained and/or unrelated sets of data.
Advantages of high cohesion:
Increased understandability of modules (simpler, fewer operations).
Increased maintainability, because changes in one module require fewer changes in other modules.
Increased reusability, because application developers will find the component they need more easily among the cohesive set of operations provided by the module.
Program structure: coupling
Coupling: the degree to which an element relies on other elements for its operation
Coupling is not a desired quality, but is a side-effect of defining different elements
to carry a common task
Much related to cohesion: good modules exhibit high cohesion and high coupling
Coupling between modules is what really needs to be avoided
Disadvantages of high coupling:
A change in one module forces a ripple effect of changes in other modules
Assembly of modules requires more effort due to the increased inter-module dependency
A module might be harder to reuse and/or test because dependent modules must be included
Contents
1. C++ program structure
2. Component and compilation unit
header file and compilation file 3. Namespaces
4. Basic terms & concepts
Program structure: header files and implementation files
header File (.h file)
Contains class declaration with free functions and operators declarations
Useful to programmers, as it is overview of a component that omits implementation details
Source File (.cpp file)
Contains free/member function definitions The .cpp file is a compilation unit
General rules:
There should be a one-to-one relationship between a given .ccp file and a
corresponding .h file, and they should have the same name.
The .cpp file #includes its corresponding .h file.
A .cpp file should never be #included, as it effectively merges two compilation units together.
Header file: example
//This is the header file dtime.h. This is the interface for the class DigitalTime.
//Values of this type are times of day. The values are input and output in
//24 hour notation as in 9:30 for 9:30 AM and 14:45 for 2:45 PM.
#ifndef
#define
DTIME_H
DTIME_H
#include
using
namespace
std;
class DigitalTime
{
:
public
DigitalTime(
int
DigitalTime( );
getHour( )
const
getMinute( )
const
void
advance(
int
minutesAdded);
void
advance(
int
hoursAdded, int
minutesAdded);
friend
bool
operator
==(const
DigitalTime& time1, const
DigitalTime& time2);
friend
istream& operator
>>(istream& ins, DigitalTime& theObject);
friend
ostream& operator
<<(ostream& outs, constDigitalTime& theObject); theHour, int theMinute); ;;private: inthour; intminute; staticvoidreadHour(int& theHour); staticvoidreadMinute(int& theMinute); };staticintdigitToInt(charc);#endif//DTIME_HConcordia University Department of Computer Science and Software EngineeringSource file: example//This is the implementation file: dtime.cpp of the class DigitalTime. //It contains all the function definitions for the function declarations in the dtime.h file. //The interface for the class DigitalTime is in the header file dtime.h. //Note that there is no class declaration in this file. #include #include #include using #include //Uses iostream and cstdlib:DigitalTime::DigitalTime(inttheHour, inttheMinute) { if(theHour < 0 || theHour > 24 || theMinute < 0 || theMinute > 59){
}
{
}
}
}
}
}
{
{
cout <<exit(1);”Illegal argument to DigitalTime constructor.”; else hour = theHour; minute = theMinute; if(hour == 24) hour = 0;DigitalTime::DigitalTime( ){ hour = 0; minute = 0;intDigitalTime::getHour( )const returnreturn
namespace
dtime.h
hour;
std;
int
DigitalTime::getMinute( )
const
minute;
// All other member functions and operators definitions declared in dtime.h should be defined here
}
Concordia University Department of Computer Science and Software Engineering
Program structure: header files
Typically, for each component there is a x.cpp and a corresponding x.h file
Any source file generally #includes their own header file.
Any source file x.cpp using entities declared/defined in another component generally will start with #include otherComponent.h
This way, during the compilation of this x.cpp, the compiler first compiles the declarations of all the entities of this component as declared in otherComponent.h.
Any file that refers to some names not declared internally file must #include the file in which these names are declared.
If a function definition is compiled that contains a function call for a function that was properly declared, this functions call needs to be resolved in order to be branched upon at runtime.
If the function is defined within the current compilation unit, it is resolved at compile time.
If the function is not defined in the current compilation unit, the linker will attempt to resolve it by
looking over what all the compilation units offer.
In Java, much of this is solved by having files named after the single class they contain.
The Java compilation model is much easier to use, though less flexible than the C++ compilation model.
Compilation unit and linkage: Example
file: one.h
class A {
int Af(int);
}
int onef(int);
file: one.cpp
#include one.h #include two.h int A::Af(int){
B myB;
myB.Bf();
}
int onef()int{
}
file: one.o
A::Af
B.Bf()
onef()
compile unit one.cpp
file: two.h
class B { int Bf();
}
class C{
}
file: two.cpp
#include two.h int B::Bf(){
}
file: two.o
B::Bf
compile unit two.cpp
Program structure: header files inclusion
A components entities declarations (classes with that member functions and free functions declaration) should always be in its header file.
Other components that use this component will #include it. There is different syntax to use if you are including a user-defined module, or an existing library module:
#include mymodule.h
Quotes indicate a user-defined module
The compiler will find it in your project directories
#include
< > indicate predefined library header file
The compiler will find it in the library directories Using different search paths
Program structure: implementation files
A components implementation code should be in a .cpp file
Give the header file and the implementation file the same name
mymodule.h and mymodule.cpp
Not enforced by the compiler, but failure to do so is confusing to other programmers
A component is composed of classes and free functions
Implementation file must #include the modules header file, as it contains the modules
classes and data structures declarations
If it does not, the compiler will complain that its on entities are undeclared
cpp files contain the executable code, i.e. function definitions Function definitions:
Functions main() function, free functions, member functions Operators free operators, member operators
Program structure: redundant includes
Header files are typically included multiple times in an applications code by different components
e.g., class declaration included by class implementation and main program file
Must only be compiled only once else, multiply defined names
No guarantee which #include in which file the compiler might see first or how many files will end up including a particular header file
Use preprocessor directives
Instructs the compiler to read a header file only once
Program structure: compilation unit
In C++, a compilation unit is a file (.cpp)
A file may contain several functions, data
structures, or classes (unlike Java)
Each compilation unit is compiled individually into an object file
The object files typically have cross- references to other object files
The linker then attempts to resolve cross- references between the object files to form the unique executable file
Handle some textual manipulation before the text is given to the compiler (looks at directive #)
e.g. provides the ability for the inclusion of header files, macro expansions, conditional compilation, and line control.
Program structure: redundant includes
Header file fname.h structure:
#ifndef FNAME_H #define FNAME_H
//Content of header file
#endif
FNAME typically name of file for consistency, readability
This syntax avoids multiple definitions from compiling the same header file more than once May also use:
#pragma once
//Content of header file
Program structure: redundant includes
In fact, this is a specialized use of the conditional compilation preprocessor directive.
Conditional compilation:
#ifdef x //or ifndef
#else #endif
Can be used to switch between portions of code by switching on/off x, e.g. machine- dependent code.
Variables (e.g. x) are macro variables used/maintained by the preprocessor.
You may encounter some legacy code that makes very heavy use of preprocessor directives.
Contents
1. C++ program structure
2. Component and compilation unit
header file and compilation file 3. Namespaces
Program structure: namespaces
Namespace: Collection of name definitions inside of a program, potentially across different files
For example, namespace std is common in libraries. Has all standard library definitions we need
#include
Includes entire standard library of name definitions
#include
using std::cout;
Can specify just the objects we want
Can be more efficient, as it avoids including things we dont use
Program structure: namespaces
Used as a solution to resolve potential name clashes Large programs use many classes and functions
As a program re-uses many other files, it increases the possibility of encountering entities that have the same name
Namespaces are meant to deal with this
A namespace can be turned on with the using namespace directive
But how to switch it off after it has been activated?
You cannot, but conveniently, the using directive is effective only in the code block in which it is used (see next slide). Use different namespaces in separated code blocks. Though this solution has its limitations.
This is one reason why the use of using NS::name directive is advocated over using namespace NS
Program structure: namespaces
Given namespaces NS1 and NS2
Both have void function myFunction()defined differently
If we want to use either definitions at different places in our program, we may do the following: {
using namespace NS1;
myFunction(); }
{
using namespace NS2; myFunction();
}
OR
{
using NS1::MyFunction(); myFunction();
}
{
using NS2::MyFunction(); myFunction();
}
Program structure: global namespace
All code goes in some namespace
Unless specified, code belongs to the global namespace
No need for using directive
Global namespace always available
But there is no way to turn it off
Thus, global namespace is prone to name clashes
Program structure: creating a namespace
To create a namespace:
namespace Space1
{
Some_Code }
Places names defined in Some_Code into namespace Space1 Can then be made available by :
using namespace Name_Space_Name
And any of the entities defined (e.g. NSentity) in it can be made available by: using Name_Space_Name::NSentity
Program structure: creating a namespace across header and implementation files
As seen earlier, header files and implementation files hold different parts of the definition/declaration of the entities in a module.
Thus, the same namespace needs to be declared in both In the header file (declarations):
namespace Space1
{
void greeting();
}
In the implementation file (definitions):
namespace Space1
{
void greeting()
{
cout << “Hello from namespace Space1.
“; }} Program structure: inline namespace qualification Can specify where name comes from Use “qualifier” and scope-resolution operator Used if only intend one use (or few) If overused, leads to less readable codeNS1::fun1(); Specifies that fun1() comes from namespace NS1 Especially useful for parameters:int getInput(std::istream inputStream); Parameter found in istreams std namespace Eliminates need for using directive or declaration Program structure: namespaces exampleConcordia University Department of Computer Science and Software Engineering Program structure: namespaces exampleConcordia University Department of Computer Science and Software Engineering Program structure: unnamed namespace Compilation unit: A .cpp file, along with all files #included in the file Thus, in you #include a .cpp file, you merge them into a single compilation unit. Avoid! Every compilation unit has its own local unnamed namespace Declared in the same way as a named namespace, but with no name All names declared in an unnamed namespace are then local to the compilation unit Use unnamed namespace to keep things “local” Scope of unnamed namespace is compilation unit Not same as global namespace Global namespace: No namespace grouping at all; global scope Unnamed namespace: Has namespace grouping, just no name; local scope Program structure: global vs. unnamed namespace example#include
namespace {
const int i = 4;
}
int i = 2;
// this is local
// this is global
int main() {
cout << i << endl; // ERROR, i is ambiguous return 0;} References Walter Savitch, Absolute C++ (Chapter 1, 11), Addison-Wesley, 2006. Bjarne Stroustrup, The C++ Programming Language (Chapters 2,6,14,15), Addison-Wesley, 2013. Y. Daniel Liang, Introduction to Programming with C++ (Chapter 2, 13). Joey Paquet COMP345 course Notes Concordia university.
Reviews
There are no reviews yet.