views:

204

answers:

2

I'm trying to use forward declarations and d-pointers to eliminate some include dependencies. Everything is working well, except that I have used XList typedefs for readability in many places (e.g: typedef QList<X> XList).

The workaround for the typedef forward declaration issue is to use inheritance: class XList : public QList<X>{};. QList has a non-virtual destructor. Given the fact that Qt's own QStringList inherits QList<QString> and I'm not allocating XLists on the heap, do you see any problems with this workaround? Should I explicitly disallow heap allocations for the XList classes?

+1  A: 

Let's have a look at what will happen if we define XList this way:

class XList : public QList<X> {};

The following will work as expected:

  XList* x = new XList;
  delete x;

However the following won't:

  QList<X>* q = new XList;
  delete q;

QList<X>'s destructor will be called but not XList's, if any. That's what a virtual destructor in the base class will do for you.

If you never use heap allocations you should be fine, but you're preparing a trap for the maintainer following you (or even yourself in a few months).

Make sure this assumption is documented and make XList's new operator private to prevent heap instantiation as you mentioned.

The safe alternative would be making QList<X> a member of your XList, that is: prefer encapsulation to inheritance.

bltxd
I've discovered that since I am using XLists as QVariant metatypes I can't make `new` private; even though I'm not doing any allocations, QVariant does. The workaround should still work, but it is getting a little too hacky for my tastes.
rpg
A: 

QStringList doesn't define its own destructor. In this case, even if QList was used polymorphically (see blue.tuxedo's example), there isn't a problem since even though the derived class destructor won't get called, there isn't one defined.

In your case, if you require a destructor in your derived class (XList), you'll run into problems. There was a previous discussion about how to get around not being able to forward declare type definitions here:

http://stackoverflow.com/questions/804894/forward-declaration-of-a-typedef-in-c

If you can avoid writing a derived class, you might be better off in the long run.

RA
This is a recipe for disaster... Just because in the current implementation in your system the undefined behavior does not bite you does not make the code correct.
David Rodríguez - dribeas
Agreed -- developers would have to remember not to write a destructor in the derived class. Someone will eventually forget, which would just cause hard-to-find problems. In that sense, you could argue that Qt is taking a risk with QStringList.
RA
While QStringList doesn't define a destructor, one will be created by the compiler since the base class has a destructor. The typedef trick also won't work because I want the client header to depend neither on X nor QList.
rpg