tags:

views:

143

answers:

6

Hi,

I need suggestions on how to solve the type of problems described below. I'm fairly new at C++ and OO-design.

I've learnt:

  1. Pointers shall be avoided when ever they can be replaced by references.
  2. Objects shall have no knowledge of objects that they don't need to know about.

But when creating objects having references to other objects we must pass these references as input arguments to the constructor. Thus we need to know about objects we should not not know anything about.

But look at the following example:

  • Suppose I have a object "Menu" that needs to have it's own timer object "Timer". I'd like to implement this association as a reference.

  • The object MenuHandler aggregates a lot of Menu objects but shall not have any knowledge about Timer objects. But when the MenuHandler creates a Menu object it must pass a Timer reference argument to the constructor. Thus, **MenuHandler must know about Timer**.

Any suggestions on how to treat these kind of problems?

+1  A: 

Why not simply make the Timer object a member (by value) of the Menu class?

Johan Levin
Thank you.I'd like to encapsulate platform dependent objects such as Timers. OK, I could place #ifdef in the Menu Class, but I want that source be totally platform independent and free from #ifdef statements. Thus it shall only know about a Timer-object and not if its a windows, linux or other timer.
Jay S
+1  A: 

I find that I produce better (more maintainable, faster, etc) code and that I'm more productive using references in C++ than I would be solving the same problem with pointers... I think the traditional answer to your example would be to have a factory object that creates menus. In this way, the MenuHandler doesn't need to know about the Timer class.

Robert Karl
Thanks.But as I understand the factory pattern, the factory returns pointers to objects created with "new". I'm trying to find out if it's possible to hide information and still use references.I'd like to use the factory pattern to create platform dependent timers without letting the timer client (Menu in my example) know anything about the platform. Still I'm worried about memory leakage and I would like to use references if possible. Is it?
Jay S
A: 

The MenuHandler creates a Timer object, passes it into the Menu constructor, and forgets about it. That seems entirely reasonable.

If the MenuHandler unnecessarily kept a reference to the Timer, that would be against the advice point #2.

Igor ostrovsky
"That seems entirely reasonable" - not to me. If you're passing a Timer by reference to a constructor, then you shouldn't simultaneously be passing responsibility for freeing it. Unless you're in the situation where Timer is always heap-allocated and menu is always stack-allocated, you'll have problems with exception-safety.
Steve Jessop
+3  A: 

I'd hesitate to bless your choice of words when it comes to the two numbered points. They're a sign you're on the right way learning C++, but they might be misleading to other novices. When I take a look at your concrete examples, this becomes more obvious.

A MenuHandler should not create menus. The content of menus is determined by by the application, so the application object (or the Controller part, if you've implemented Model-View-Controller) should create menus. The MenuHander merely takes ownership of menus created elsewhere.

Also, it may make sense to give each menu its own timer. That means the relation can be described as "Has a"; the menu has a timer. The relationship usually implmented by references can be described as "Knows a" (the inheritance relationship is usally called "Is a"). If each Menu object has a Timer, it can be a member, and initialized by the Menu constructor(s). The Timer object internally may obtain a reference to the system clock in its constructor, but that's not your concern.

MSalters
A: 

In a more general case where you need to provide a class to another class in order to do some kind of callback, you avoid mutual dependency (both know each other) by using an interface. Class A derives from the interface. Class B accepts the interface as paramater in the constructor and calls the virtual function from that interface when needed. Also check the observer design pattern.

stefaanv
A: 

For #1 Be very careful with the lifetime of your objects. References are no that suitable to handle dynamic graph of objets ( like your menu, menuhandler, timer, etc... ). What if you want to change the timer object later ?

It's not a good idea to have references as members in a class if the lifetime of referenced objects is not really known.

Avoiding pointer does not mean using references everywhere, you should have a look at smart pointers which will be more suitable for what you want to do.

fa.