...
Using the same class definitions as the noncompliant code example, this compliant solution modifies the definition of f()
to require raw pointers to the object, removing the slicing problem:.
Code Block | ||||
---|---|---|---|---|
| ||||
// Remainder of code unchanged... void f(const Employee *e) { if (e) { std::cout << *e; } } int main() { Employee coder("Joe Smith"); Employee typist("Bill Jones"); Manager designer("Jane Doe", typist); f(&coder); f(&typist); f(&designer); } |
This compliant solution also complies with EXP34-C. Do not dereference null pointers in the implementation of f()
. With this definition, the the program correctly outputs :the following.
Code Block |
---|
Employee: Joe Smith Employee: Bill Jones Manager: Jane Doe Assistant: Employee: Bill Jones |
...
An improved compliant solution, which does not require guarding against null pointers within f()
, uses references instead of pointers:.
Code Block | ||||
---|---|---|---|---|
| ||||
// ... Remainder of code unchanged ... void f(const Employee &e) { std::cout << e; } int main() { Employee coder("Joe Smith"); Employee typist("Bill Jones"); Manager designer("Jane Doe", typist); f(coder); f(typist); f(designer); } |
...
This compliant solution uses a vector of std::unique_ptr
objects, which eliminates the slicing problem:.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> #include <memory> #include <string> #include <vector> void f(const std::vector<std::unique_ptr<Employee>> &v) { for (const auto &e : v) { std::cout << *e; } } int main() { std::vector<std::unique_ptr<Employee>> v; v.emplace_back(new Employee("Joe Smith")); v.emplace_back(new Employee("Bill Jones")); v.emplace_back(new Manager("Jane Doe", *v.front())); f(v); } |
...