CS 250 Computer Programming and Problem Solving - FALL 1998 

[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]


Sections of chapter 6 and 7 to be deferred:


Chapter 6: More on Derived Classes


Derived Classes (Access Specifiers)

Description The access arrangements between a base class and a derived class
and between the derived/base class and the public
are controlled by the Access Specifiers public, private and protected

These specifiers are used for the members of the base and derived classes and for the inheritance relationships itself.

Inheritance Relationship Access Specifiers: the derived class can use either public or private inheritance:

  • public: this permits public members of the base class to be public members of the derived class
  • private: this prevents access to the public members of the base class by public users of the derived class.

Base Class Members Access Specifiers:

  • public: derived class can access these members, so can the public in public inheritance (this is familiar one)
  • private: only base class functions and friends can access these members (also familar)
  • protected: only derived class functions can access these base class members, not accessible by the public of either the base or derived class.
Syntax Inheritance Relationship Access Specifier:

class derivedClassName : public baseClassName { .... }

class derivedClassName : private baseClassName { .... }

Base Class Members Access Specifiers:

class className {
    public: members
  
private: members
   
protected: members
}

Examples
(more examples)
class  ClassA {
public:
  int VarA1;
private:
   int VarA2;
protected:
  int
VarA3;
}

class ClassB: public ClassA {
// can access VarA1 and VarA3 but NOT VarA2
public:
   int VarB1;
private:
   int VarB2;
}

class ClassC: private ClassA {
// can access VarA1 and VarA3 but NOT VarA2
public:
   int
VarC1;
private:
   int
VarC2;
}

ClassA object1;
ClassB object2;
ClassC object3;

object1.VarA1 = 2; // OK
object1.VarA2 = 2; // NOT OK
object1.VarA3 = 2; // NOT OK

object2.VarA1 = 2; // OK
object2.VarA2 = 2; // NOT OK
object2.VarA3 = 2; // NOT OK
object2.VarB1 = 2; // OK
object2.VarB2 = 2; // NOT OK

object3.VarA1 = 2; // NOT OK
object3.VarA2 = 2; // NOT OK
object3.VarA3 = 2; // NOT OK
object3.VarC1 = 2; // OK
object3.VarC2 = 2; // NOT OK

Tips
  • Protected access to data members should be discouraged (like public access to data), it is better to use protected members functions to access private data for that purpose
  • protected access assumes you are expecting to be used in an inheritance relationship, otherwise it has no benefit.

 


 

Chapter 7: Dynamic Allocation and Classes


Copy Constructors

Description Special Purpose Constructor that makes a duplicated copy of an object of the same type. Used in the following circumstances:
  • When defining an object initialized as a copy of an existing object
  • When passing an object using call by value
  • When returning an object of this type from a function
  • It is not used for Assignment
Syntax className(const className & parameterName);

 

Examples
(more examples)
class  ClassA {
public:
 
ClassA(const ClassA & theObject);
private:
   int VarA1;
}

ClassA::ClassA(const ClassA & theObject)
{
   VarA1 = theObject.VarA1;
   return *this;
}

ClassA a1;
...
ClassA a2(a1); // a2 is a copy of a1
ClassA a3 = a1; // a3 is a copy of a1

....
ClassA someFunction(ClassA theParameter) // call by value uses copy constructor
{
   ClassA localVariable;
.....
   return localVariable; // copy constructor used to copy to temporary return object

}

....

cout << someFunction(a1); // temporary object returned by someFunction is printed out

 

Tips
  • If not explicitely defined, one is created automatically which makes a memberwise copy of the object. Uses bitwise copy for built in data types.
  • If object uses dynamic memory allocation, the automatically defined copy constructor will only give a shallow copy. To get a deep copy need to define a copy constructor

 

 


 

#include <iostream.h>
class classA {
    friend ostream & operator <<(ostream & os, const classA & theObject);
public:
   classA();
   classA(const classA& obj);
   void update();
private:
   int * p;
};

classA::classA()
{
   p = new int[10]; // allocate space for array
   for(int i=0; i<10;i++)
   	p[i] = i; // note use of array notation with pointer
}

classA::classA(const classA & obj)
{
   p = new int[10]; 
   for(int i = 0; i<10; i++)
	p[i] = obj.p[i]; // note naming for two objects

}
void classA::update()
{
   for(int i = 0; i< 10; i++)
	p[i] += 10;
}
ostream & operator<<(ostream & os, const classA & theObject)
{
   for(int i=0;i<10;i++)
	cout << " " << theObject.p[i];
   cout << endl;
   return os;
}

void main()
{
   classA a1;
   cout << "a1 initially:" << a1;
   a1.update();
   cout << "a1 after update:" << a1;
   classA a2(a1); // uses copy constructor
   cout << "a2 initially:" << a2;
   a2.update();
   cout << "a2 after update:" << a2;
   classA a3 = a2; // uses copy constructor
   cout << "a3 initially:" << a3;
   classA a4;
   cout << "a4 initially:" << a4;
   a4 = a1; // does not use copy constructor (shallow copy)
   cout << "a4 after assignment:" << a4;
   a1.update();
   cout << "a1 after update:" << a1;
   cout << "a4 after update:" << a4;
	
}

 

// p239.cpp  - VString Class Example, p. 239

// This introduces the beginnings of a Variable-length string class.

#include <string.h>
#include <iostream.h>

class VString {
public:
  VString( unsigned len = 0 ); // default (optional) parameter
  // Construct a VString of size <len>.

  VString( const char * s );
  // Construct a VString from a C-style string.

  VString(const Vstring & v);
  // copy constructor;

  ~VString();
  // Destructor

  unsigned GetSize() const;
  // Return the number of characters.

private:
  char * str;      // character array
  unsigned size;   // allocation size
};

VString::VString( unsigned len )
{
  size = len;
  str = new char[ size+1 ];
  str[0] = '\0';
}

VString::VString( const char * s )
{
  size = strlen( s );
  str = new char[ size+1 ];
  strcpy( str, s );
}

VString::Vstring(const VString & v)
{
  size = v.size;
  str = new char[size+1];
  strcpy(str,v.str);
  return *this;
}

VString::~VString() // free up allocated memory (prevent memory leaks)
{
  delete [] str;
}

unsigned VString::GetSize() const
{
  return size;
}


int main()
{

VString zeroLen;
VString emptyStr( 50 );
VString aName( "John Smith" );
VString bName(aName);
cout << aName.GetSize() << endl;

 return 0;
}

 

// p248.txt - LongArray Class Definition

class LongArray {
public:
  LongArray( unsigned sz = 0, long defval = 0 );
  // Construct an array of size sz, initialize all
  // elements with defval.

  LongArray( const LongArray & L );
  // Copy constructor.

  ~LongArray();
  // Destructor.

  unsigned GetSize() const;
  // Return the current allocation size.

  void GrowBy( unsigned n );
  // Increase the allocation size by n elements.

  void Init( long defval = 0 );
  // Initialize all elements to defval.

  long Get( unsigned i ) const;
  // Retrieve element at index position i.

  void Put( unsigned i, long elt );
  // Insert element at index position i.

private:
  long * data;   // ptr to array containing elements
  unsigned size; // current allocation size
  long initv;    // initial value
};


// p250.txt - LongArray Class Implementation

#include "long.h"

LongArray::LongArray( unsigned sz, long defval )
{
  size = sz;
  data = new long[size];
  Init( defval );
}

LongArray::LongArray( const LongArray & L )
{
  size = L.size;
  initv = L.initv;
  data = new long[size];
  for(unsigned i = 0; i < size; i++)
    data[i] = L.data[i];
}

LongArray::~LongArray()
{
  delete [] data;
}

long LongArray::Get( unsigned i ) const
{
  assert( i < size );
  return data[i];
}

unsigned LongArray::GetSize() const
{
  return size;
}

void LongArray::GrowBy( unsigned growBy )
{
  unsigned tsize = size + growBy;
  long * temp = new long[tsize];

  // Copy the existing data.
  unsigned i;
  for(i = 0; i < size; i++)
    temp[i] = data[i];

  // Set new positions to initial values.
  for(i = size; i < tsize; i++)
    temp[i] = initv;

  size = tsize;   // update the size value
  delete [] data; // delete the old array
  data = temp;    // save pointer to new data
}

void LongArray::Init( long defval )
{
  initv = defval;
  for(unsigned i = 0; i < size; i++)
    data[i] = defval;
}

void LongArray::Put( unsigned i, long elt )
{
  assert( i < size );
  data[i] = elt;
}



Copyright chris wild 1998.
For problems or questions regarding this website contact [Chris Wild (e-mail:wild@cs.odu.edu].
Last updated: October 14, 1998.