Programming Workshop 2 (CSCI 1061U)
Faculty of Science, Ontario Tech University
Consider class Vec definition below
class Vec {
protected:
float d[3];
(float x, float y, float z) {
Vec[0] = x;
d[1] = y;
d[2] = z;
d}
float length2() const;
};
Now consider two possible implementations of the length() method.
Implementation 1
float Vec::length() const
{
float squared_sum = 0.0;
for (int i=0; i<3; ++i) {
+= (d[i]*d[i]);
squared_sum }
return squared_sum;
}
Implementation 2
float Vec::length() const
{
return d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
}
Notice the actual implementation of method length() doesn’t change how this class may be used as seen below
(1,2,3);
Vec v1<< "length of v1 is " << v1.length() << endl; cout
private
#include <iostream>
See example below. We define Vec class in Vec.h file.
// Vec.h
class Vec {
protected:
float d[3];
(float x, float y, float z);
Vec
float length2() const;
};
And we implement Vec in Vec.cpp file.
// Vec.cpp
#include "Vec.h"
::Vec(float x, float y, float z)
Vec{
[0] = x;
d[1] = y;
d[2] = z;
d}
float Vec::length2() const
{
return d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
}
Consider class A defined in header A.h. This class is used in various places in the program.
// A.h
class A { ... };
The class implementation resides in A.cpp
// A.cpp
...
Say this class is used in the files B.cpp, C.cpp and D.cpp.
B.cpp
// B.cpp
#include "A.h"
...
C.cpp
// C.cpp
#include "A.h"
...
D.cpp
// D.cpp
#include "A.h"
...
Contents in A.h will be compiled everytime files B.cpp, C.cpp and D.cpp are compiled. We can avoid this by using preprocessor directives, telling the compiler to compile the contents of A.h only once, as follows:
// A.h
#ifndef FNAME_H
#define FNAME_H
class A { ... };
#endif
#ifndef
, #define
and #endif
are preprocessors that can be used to exclude portions of code
from compilation. Label FNAME is typically filename for consistency and
readability. E.g., FNAME_H is often chosen as __A_H__
.
This prevents the contents of A.h to be compiled multiple times.
using
directive to pull in the names of
members/functions defined in a particular namespace
cout
is defined in namespace std
.
We have the following three choices to use this in the code:
using namespace std; ... cout << ... ;
using std::cout; ... cout << ...;
using
directive or one of its other variants
(see above).namespace1::func();
and
namespace2::func()
. I.e., we must specify which namespace
to use at what time.using
directive only pulls in the name in the current
scope. So if using
directive is used inside a function,
then the names in the namespace will only be visible in that
function.Example 1
Given namespace NS1 and NS2
{
using namespace NS1;
();
func}
{
using namespace NS2;
();
func}
Or
::func();
NS1::func(); NS2
namespace
keyword to define a namespace
groupingnamespace NS
{
// Code goes here
}
Example 1
namespace csci1061
{
class Vec {
};
}
Then we will use the file as follows
using namespace csci1061;
; Vec v
or
::Vec v; csci1061
or
using csci1061::Vec;
; Vec v
Example 2
namespace NS1
{
void greeting();
}
namespace NS1
{
void greeting() { cout << "Hello world." << endl; }
}
Makes only one (the specified) name available, as seen below. This prevents any other uses of the name.
using NS1::getting;
Makes all names in the namespace available.
using namespace NS1;
It is possible to have nested namespaces
namespace NS1 {
{
namepace NS2 namespace NS3 {
void func() { ... }
}
}
}
We cam use func() as follows
::NS2::NS3::func(); NS1
Recall that we want to keep class implementation hidden from the user of that class. Similarly, we may want to hide helping functions (local level utilities used within other methods within a file, but not available to methods in other files) as well.
We can hide helping functions by making these private, or we can place these functions in class implementations unnamed space.
Consider the following two files: a.cpp
and
b.cpp
. Here anonymous namespace is used to hide method
product
in b.cpp
from methods in file
a.cpp
.
a.cpp
// Faisal Qureshi
// faisal.qureshi@ontariotechu.ca
// March 29, 2021
//
// File a.cpp
#include <iostream>
using namespace std;
int sum(int a, int b);
int product(int a, int b);
int product_for_others(int a, int b);
int main()
{
<< sum(10,20) << endl;
cout
// cout << product(10,20) << endl; // This line gives an error since
// function int product(int a, int b)
// is within an anonymous namespace
// in b.cpp
// So this function is only visible to
// other methods in b.cpp
// This behavior is similar to
// using a method with a static keyword
// before
<< product_for_others(10,20) << endl; // This works. Note that
cout // product_for_others actually
// uses the product method defined
// in b.cpp
return 0;
}
b.cpp
// Faisal Qureshi
// faisal.qureshi@ontariotechu.ca
// March 29, 2021
//
// File b.cpp
// This function is available outside of this file
int sum(int a, int b) {
return a+b;
}
namespace
{
// This function is only available to other functions
// in this file
int product (int a, int b) {
return a*b;
}
}
// This function is available outside of this file
int product_for_others(int a, int b){
return a*b;
}