FAQ 2.21 What are the basics of defining a class that contains a pointer to an object allocated from the heap?

graphics/new_icon.gif

Overview: (1) Try to avoid this situation. (2) If it can't be avoided, use an auto_ptr.

Try to avoid defining a class that contains a pointer to an object allocated from the heap. For example, consider the situation where a car contains an engine. There are two choices: the preferred way would be for the engine object to be physically embedded inside the car object, and the undesirable way would be for the car object to contain a pointer to the engine object, where the car allocates the engine object from the heap. Here is a sample Engine class:

 #include <iostream> using namespace std; class Engine { public:   Engine();   virtual void start(); }; Engine::Engine() {   cout << "Engine constructor\n"; } void Engine::start() {   cout << "Engine::start()\n"; } 

The car class shown in the following code, class Car, uses the preferred approach: each Car object physically contains its Engine object. Compared to using a pointer to an Engine allocated from the heap, the technique shown in class Car is easier, safer, and faster, and it uses less memory.

 class Car { public:   Car();   virtual void startEngine(); protected:   Engine e_;                                         <-- 1 }; Car::Car() : e_ ()                                              <-- 2 {   // Intentionally left blank } void Car::startEngine() {   e_.start();                                        <-- 3 } 

(1) Physically embed an Engine object inside every Car object

(2) Initialize the Engine object that's inside the Car object

(3) Call the start() member function of the Engine object

Although this is the preferred approach, sometimes it is necessary, or perhaps expedient, to allocate the inner object from the heap and have the outer object contain a pointer to the inner object. When this happens, an auto_ptr should be used:

 #include <memory>                                    <-- 1 using namespace std; typedef auto_ptr<Engine> EnginePtr; class Car { public:   Car();   virtual void startEngine();   virtual ~Car();   Car(const Car& c);                                 <-- 2   Car& operator= (const Car& c);                     <-- 3 protected:   EnginePtr p_;                                      <-- 4 }; Car::Car() : p_ (new Engine())                                  <-- 5 {   // Intentionally left blank } void Car::startEngine() {   p_->start();                                       <-- 6 } 

(1) To get auto_ptr

(2) This can be ignored for now; see FAQ 30.12

(3) This can be ignored for now; see FAQ 30.12

(4) Every Car object contains an auto_ptr to its Engine object

(5) Allocate an Engine object for the Car object

(6) Call the start() member function of the Engine object

Logically this second example is still a contains or has-a relationship, but physically the implementation is somewhat different. Note the three extra member functions that must be declared in the second version of class Car. These extra member functions are needed because an auto_ptr is used to hold the car's Engine object.

The most important message here is that it is much less dangerous to use auto_ptr than to use a raw hardware pointer, such as Car*. Thus the following technique should not be used.

 class Car { public:   Car();   virtual void startEngine();   virtual ~Car();   Car(const Car& c);                                 <-- 1   Car& operator= (const Car& c);                     <-- 2 protected:   Engine* p_;                                        <-- 3 }; 

(1) This can be ignored for now; see FAQ 30.10

(2) This can be ignored for now; see FAQ 30.10

(3) Bad form: Try to avoid raw hardware pointers toallocated objects

The particular dangers of using raw hardware pointers are outlined later in the book, but for now simply use an auto_ptr as shown in the second example.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net