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) {
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
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"
float x, float y, float z)
Vec::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
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 of the class, but not for general consumption) as well.
We can hide helping functions by making these private, or we can place these functions in class implementations unnamed space.