Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This code example is non-compliant because of the unintended data loss.

Code Block
bgColor#FFCCCC
langcpp
class Employee {
public:
  Employee(string theName) : name(theName) {};
  string getName() const {return name;}
  virtual void print() const {
    cout << "Employee: " << getName() << endl;
  }
private:
  string name;
};

class Manager : public Employee {
public:
  Manager(string theName, Employee theEmployee) :
    Employee(theName), assistant(theEmployee) {};
  Employee getAssistant() const {return assistant;}
  virtual void print() const {
    cout << "Manager: " << getName() << endl;
    cout << "Assistant: " << assistant.getName() << endl;
  }
private:
  Employee assistant;
};

int main () {
  Employee coder("Joe Smith");
  Employee typist("Bill Jones");
  Manager designer("Jane Doe", typist);

  coder = designer;  // slices Jane Doe!
  coder.print();
}

...

Assuming exactly the same class structure as above, if pointers to the objects are used so that objects are copied by reference, then slicing does not occur.

Code Block
bgColor#ccccff
langcpp
int main () {
  Employee *coder = new Employee("Joe Smith");
  Employee *typist = new Employee("Bill Jones");
  Manager *designer = new Manager("Jane Doe", *typist);

  coder = designer;
  coder->print();
}

...

Alternatively, it is often safer to use a smart pointer, like std::auto_ptr, to hold the address of allocated memory. This is typically more robust than the use of raw pointers.

Code Block
bgColor#ccccff
langcpp
int main () {
  auto_ptr<Employee> coder( new Employee("Joe Smith") );
  auto_ptr<Employee> typist( new Employee("Bill Jones") );
  auto_ptr<Manager> designer( new Manager("Jane Doe", *typist) );

  coder = designer; // Smith deleted, Doe xferred
  coder->print();
  // everyone deleted
}

...

Alternatively, references may be used to refer to the various derived employee objects.

Code Block
bgColor#ccccff
langcpp
int main () {
  Employee coder("Joe Smith");
  Employee typist("Bill Jones");
  Manager designer("Jane Doe", typist);

  Employee &toPrint = designer;  // Jane remains entire
  toPrint.print();
}

...

The most effective way to avoid slicing of objects is to ensure, whenever possible, that polymorphic base classes are abstract.

Code Block
bgColor#ccccff
langcpp
class Employee {
public:
  Employee(string theName) : name(theName) {};
  virtual ~Employee();
  string getName() const {return name;}
  virtual void print() const = 0;
private:
  string name;
};

...