There is no hard and fast rule:
As people have mentioned using references inside objects can cause copy problems (and it does) so it is not a panacea, but for certain situation it can be useful (that is why C++ gives us the option to do it all these different ways). But using RAW pointers is really not an option. If you are dynamically allocating objects then you should always be maintaining them with smart pointers and your object should also be using smart pointers.
For people who demand examples: Streams are always passed and stored as references (as they can’t be copied).
Some Comments on your code examples:
Example one and two
Your first example with pointers. Is basically the same as the second example using references. The difference being that a reference can not be NULL. When you pass a reference the object is already alive and thus should have a lifespan greater than the object you are testing already (If it was created on the stack) so it should be safe to keep a reference. If you are dynamically creating pointers as dependencies I would consider using boost::shared_pointer or std::auto_ptr depending if ownership of the dependency is shared or not.
Example Three:
I don’t see any great use for your third example. This is because you can not use polymorphic types (If you pass an object derived from Dependency it will be sliced during the copy operation). Thus the code may as well be inside Addict rather than a separate class.
Bill Harlen: (http://billharlan.com/pub/papers/Managing%5FCpp%5FObjects.html)
Not to take anything away from Bill But:
- I have never heard of him.
- He is a Geo-Physists not a computer programmer
- He recomends programming in Java to improve your C++
- The languages are now so different in usage that is utterly false).
- If you want to use references of What to-do/not to-do.
Then I would pick one of the Big names in the C++ field:
Stroustrup/Sutter/Alexandrescu/Meyers
Summary:
- Don’t use RAW pointers (when ownership is required)
- Do use smart pointers.
- Don’t copy objects into your object (it will slice).
- You can use references (but know the limitations).
My example of Dependency injection using references:
class Lexer
{
public: Lexer(std::istream& input,std::ostream& errors);
... STUFF
private:
std::istream& m_input;
std::ostream& m_errors;
};
class Parser
{
public: Parser(Lexer& lexer);
..... STUFF
private:
Lexer& m_lexer;
};
int main()
{
CLexer lexer(std::cin,std::cout); // CLexer derived from Lexer
CParser parser(lexer); // CParser derived from Parser
parser.parse();
}
// In test.cpp
int main()
{
std::stringstream testData("XXXXXX");
std::stringstream output;
XLexer lexer(testData,output);
XParser parser(lexer);
parser.parse();
}