Code to demo Item 31 in Effective C++


Souce code list.
Address.h
 
class Address {
};
 
Date.h
 
class Date {
};

 
PersonImpl.h
 
#include <string>
#include <tr1/memory>
using namespace std;

class Date;
class Address;

class PersonImpl {
  public:
    PersonImpl(const string& name, const Date& birthday, const Address& addr);
    string name() const;
    Date birthday() const;
    Address address() const;
  private:
    string theName;
    Date theBirthDate;
    Address theAddress;
};

 
PersonImpl.cpp
 
#include <string>
#include <iostream>
using namespace std;

#include "Date.h"
#include "Address.h"
#include "PersonImpl.h"

PersonImpl::PersonImpl(const string& name, const Date& birthday, const Address& addr) 
  : theName(name), theBirthDate(birthday), theAddress(addr) {
}

string PersonImpl::name() const {
  return theName;
}

Date PersonImpl::birthday() const {
  return theBirthDate;
}

Address PersonImpl::address() const {
  return theAddress;
}

 
Person.h
 
#include <string>
#include <tr1/memory>
using namespace std;

class PersonImpl;
class Date;
class Address;

class Person {
  public:
    Person(const string& name, const Date& birthday, const Address& addr);
    string name() const;
    Date birthday() const;
    Address address() const;
  private:
    tr1::shared_ptr<PersonImpl> pImpl;
};

 
Person.cpp
 
#include "Date.h"
#include "Address.h"
#include "Person.h"
#include "PersonImpl.h"

Person::Person(const string& name, const Date& birthday, const Address& addr)
  : pImpl(new PersonImpl(name, birthday, addr)) {
}

string Person::name() const {
  return pImpl->name();
}

Date Person::birthday() const {
  return pImpl->birthday();
}

Address Person::address() const {
  return pImpl->address();
}

 
main.cpp
 
#include <iostream>
using namespace std;

#include "Date.h"
#include "Address.h"
#include "Person.h"

int main(int argc, const char *argv[]) {
  string name = "yaojg";
  Date d;
  Address addr1;
  Person p(name, d, addr1);

  cout << "here we go" << endl;

  return 0;
}

 
Compile and run:
g++ -c PersonImpl.cpp
g++ -c Person.cpp
g++ *.o -o run
./run
 
One thing worth of mention is Person.cpp. If I have include Address.h before PersonImpl.h, the following error will show up:
 
field ‘theAddress’ has incomplete type
 
 
The reason is that PersonImpl needs Address to be compiled. So Address defintion must occurs textually before PersonImpl definition. At this point, C++ is different from Java. In Java, textual layout is unimportant in most of situations.