Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm wondering whether it is better to make object fields within a class objects or pointers. Specifically it seems that using an object field requires the entire header for that object's class to be included, where as with an object pointer you can get by with a simpler forward class declaration.

For example, which is better, an object field:

Classifier.h

#include "normalizer.h"

class Classifier {
 public:
  Classifier(const Normalizer& normalizer);
 private:
  const Normalizer normalizer_;
};

Classifier.cpp

#include "classifier.h"
#include "normalizer.h"

Classifier::Classifier(const Normalizer& normalizer)
    : normalizer_(normalizer) {}

Or an object pointer field:

Classifier.h

class Normalizer;

class Classifier {
 public:
  Classifier(const Normalizer& normalizer);
 private:
  const Normalizer* normalizer_;
};

Classifier.cpp

#include "normalizer.h"

Classifier::Classifier(const Normalizer& normalizer)
    : normalizer_(new Normalizer(normalizer)) {}

Classifier::~Classifier() {
  delete normalizer_;
}
share|improve this question

closed as off-topic by Jamal Feb 21 at 18:51

  • This question does not appear to be a code review request within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

    
This question appears to be off-topic because it is primarily a design review. –  Jamal Feb 21 at 18:51

2 Answers 2

up vote 4 down vote accepted

They should definately by objects in nearly all situations (there are exceptions).

What you have described above is the PIMPL pattern (also see pimpl vs brige).
This allows you to abstract and hide implementation details from the user of your class (a sometimes useful technique).

Note: There is a problem with your second example is that you have not specified ownership semantics (and thus not correctly implemented the rule of three (which can be fixed by using smart pointers rather than RAW pointers)).

The claim of the advantage that "forward declaration is simpler" is not true. What you are doing is shifting responsibility. If you use objects in your class then you need to included the header files. If you use pointers then you only need forward declarations. But at some point when the object is used you need to include its header file. So all you have done is shift the point at where the header file needs to be included. If you put it in your header file the user does not need to know (and thus is not tightly coupled) about any dependencies inside your objects (they just include your header).

share|improve this answer
    
Could you please expand on why the ownership semantics in the example given are not correct? The Classifier instance owns its own copy of the Normalizer which it is responsible for deleting. What am I missing here? Thanks! –  padawan Nov 11 '12 at 15:24
1  
@padawan: You forgot the copy and assignment operators (you are deleting something that you may potentially not own as there may be other copies (as such the ownership semantics are not well defined). If you are going to hold a pointer hold it in a smart pointer. std::unique_ptr would be appropriate here (note this may not be appropriate as it prevents copying (but not moving)). –  Loki Astari Nov 11 '12 at 15:29

I will attempt to answer the member-vs-pointer question generally.

These are the consequences of making the inner object itself a member of the outer object:

  • The entire object's data will be contained within the outer object. This may have memory usage implications, if the inner object is a large one.
  • The inner object must exist for the entire lifetime of the outer object; no more and no less. And there must be a 1-to-1 mapping of inner to outer objects.
  • Because there is no pointer indirection, access to the inner is faster (but not always!).
  • There are no special memory management concerns - the compiler takes care of allocation, construction and destruction in the outer object's constructer and destructor.
  • The header for the outer class needs to include the header for the inner class.

And of course if the member is a pointer, the reverse of all of the above applies.

One of the key concerns with using pointers is making sure memory is properly managed. In C++ this can be almost entirely mitigated with proper use of smart_ptr (or auto_ptr if you can't get smart_ptr for some reason).

Don't try too hard to make things easier for the compiler. If you want your inner object to be a member, then let the compiler read that header file. It's a tool, make it work.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.