Example 1 - Review of classes, constructors and destructors

// Review Example 1

#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;

class Name
{
	char* name_;
public:
	Name();
	Name(const char* name);
	Name(const Name&);
	~Name();
	const char* get_name() const { return name_ ? name_ : ""; }
	void set_name(const char* name);
	const char* firstName() const;
	char* lastName() const;
};

Name::Name()
: name_(0)
{
}

Name::Name(const char* name)
: name_(new char[strlen(name)+1])
{
	strcpy(name_,name);
}

Name::Name(const Name& other)
: name_(new char[strlen(other.name_)+1])
{
	strcpy(name_,other.name_);
}

Name::~Name()
{
	if (name_) {
		delete[] name_;
		name_ = 0;
	}
}

void Name::set_name(const char* name)
{
	delete[] name_;
	name_ = new char[strlen(name)+1];
	strcpy(name_,name);
}

const char* Name::firstName() const
{
	const char* ptr = strchr(name_,',');
	if (!ptr) {
		return name_;
	}
	// skip over whitespace text
	while (ptr) {
		if (isalpha(*ptr))
			break;
		else
			++ptr;
	}
	return ptr;
}

char* Name::lastName() const
{
	static char* ptr = 0;
	if (ptr) {
		delete [] ptr;
	}
	ptr = new char[strlen(name_)+1];
	strcpy(ptr,name_);

	strtok(ptr,",");
	return ptr;
}


int main()
{
	Name joe("Bentley, Joe");
	Name john("Doe,John");
	Name jane("Doe,      Jane");
	Name mary("Mary");
	Name nobody;
	Name clone(john);

	cout << joe.get_name() << endl;
	cout << john.firstName() << endl;
	cout << jane.lastName() << endl;
	cout << mary.get_name() << ' ' << mary.firstName() << ' ' << mary.lastName() << endl;
	cout << nobody.get_name() << endl;
	cout << clone.get_name() << endl;
}

Review Questions

  1. Is the default constructor necessary?
  2. Is the copy constructor necessary?
  3. How can you "avoid" writing the default constructor?
  4. Are the constructor initializers necessary?
  5. Can you write the default's constructor initializer as : name_("") ?
    What are the ramifications?
  6. Why does the Name::firstName() return const char* and the Name::lastName() return char* ?
  7. Why does Name::get_name() return name_ ? name_ : "" and not just return name_ ?