Programming Workshop 2 (CSCI 1061U)
Faculty of Science, Ontario Tech University
Consider class Vec definition below
class Vec {
protected:
float d[3];
Vec(float x, float y, float z) {
d[0] = x;
d[1] = y;
d[2] = z;
}
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) {
squared_sum += (d[i]*d[i]);
}
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
Vec v1(1,2,3);
cout << "length of v1 is " << v1.length() << endl;private#include <iostream>See example below. We define Vec class in Vec.h file.
// Vec.h
class Vec {
protected:
float d[3];
Vec(float x, float y, float z);
float length2() const;
};And we implement Vec in Vec.cpp file.
// Vec.cpp
#include "Vec.h"
Vec::Vec(float x, float y, float z)
{
d[0] = x;
d[1] = y;
d[2] = z;
}
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
NS1::func();
NS2::func();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
csci1061::Vec v;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
NS1::NS2::NS3::func();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()
{
cout << sum(10,20) << endl;
// 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
cout << product_for_others(10,20) << endl; // This works. Note that
// 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;
}