Class Subtleties

Tom Kelliher, CS23

Feb. 28, 1996

Fine Points of Classes

  1. #ifndef/#endif
  2. Name overloading
  3. Class initialization (following the signature)
  4. #ifdef
  5. Defining methods in class declarations
  6. inline
  7. The copy constructor
  8. The best way to print a class instance?

string.h:

#ifndef __STRING_H
#define __STRING_H

#include <iostream.h>

class String
{
 public:
   // String is overloaded, the two constructors have different
   // signatures, however.
   String(const char*);
   String(void) : str(NULL), len(0)
   {
#ifdef DEBUG
      cout << "String's constructor executing\n";
#endif
   }
   String(const String&);   // copy constructor
   ~String(void)
   {
#ifdef DEBUG
      cout << "String's destructor executing\n";
#endif
      delete[] str;
   }
   const char* Print(void);

 private:
   char *str;
   int len;
};
#endif

string.cc:

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

String::String(const char* s)
{
#ifdef DEBUG
   cout << "String's constructor executing\n";
#endif
   len = strlen(s);
   if (len != 0)   // ugly hack
   {
      str = new char[len + 1];   // simplistic, the '\0' is unnecessary
      assert (str != NULL);

      strcpy(str, s);
   }
   else
      str = NULL;
}

String::String(const String& S) : len(S.len)
{
#ifdef DEBUG
   cout << "String's copy constructor executing\n";
#endif
   if (len != 0)   // required due to preceding ugly hack
   {
      str = new char[len + 1];
      assert (str != NULL);

      strcpy(str, S.str);
   }
   else
      str = NULL;
}

const char* String::Print(void)
{
   return str;   // dependent upon str being '\0' terminated --- you
                 // should avoid this on homework 2
}

  1. Default initializations
  2. Class members of classes (distinct from base class)
  3. Word needs no copy constructor, but String does???

word.h

#ifndef __WORD_H
#define __WORD_H

#include <stdlib.h>
#include "string.h"

class Word
{
 public:
   Word(char* = NULL, int = 1);
   ~Word(void);
   const char* Print(void);
   Count();
 private:
   String word;   // word is a class instance
   int count;
};
#endif

word.cc:

#include <iostream.h>
#include <assert.h>
#include "word.h"

Word::Word(char *s, int cnt) : word(s)
{
#ifdef DEBUG
   cout << "Word's constructor executing\n";
#endif
   count = cnt;
}

Word::~Word(void)
{
#ifdef DEBUG
   cout << "Word's destructor executing\n";
#endif
}

const char* Word::Print(void)
{
   return word.Print();   // interesting
}

int Word::Count(void)
{
   return count;
}

A modest driver program, main.cc:

#include <iomanip.h>
#include <iostream.h>
#include "string.h"
#include "word.h"

void f(Word);

int main(void)
{
   cout << "main() starting\n";

   String s1("Hello world");
   String s2;
   String s3 = s2;
   Word w1("Rosebud");
   Word w2 = w1;

   cout << s1.Print() << endl;
   cout << s2.Print() << endl;
   cout << w1.Print() << setw(5) << w1.Count() << endl;

   f(w2);

   cout << "main() finishing\n";
}

void f(Word w)
{
   cout << "f() starting/finishing\n";
}

Lab Exercise

  1. Pick up the five files in ~kelliher/pub/cs23/classes/. Put them in a directory with no other files.
  2. To compile:
    g++ -o main *.cc
    
    Why *.cc?
  3. Fix the nasty syntax errors. (The code in the lecture notes is right; don't peek at it too quickly.)
  4. To see the debugging messages and add debugging symbols for gdb:
    g++ -g -o main -DDEBUG *.cc
    
  5. Run main directly to see what the output looks like. Is it what you expected?
  6. Run main under gdb, to get accustomed to using the debugger and to gain an understanding of when constructors, destructors, and copy constructors are called:
    1. Run gdb on main.
    2. Set a breakpoint for main().
    3. Run the program. The program should stop at the first line of main().
    4. Single step the program using step. Pay close attention to the order of the various method and function calls. It is very important that you understand why all the calls are occurring.


Thomas P. Kelliher
Tue Feb 27 12:35:20 EST 1996
Tom Kelliher