Are C++ polymorphic classes without any functions possible?

c++, polymorphism

Solution

If you add a virtual function, the classes will get a vtable so that `dynamic_cast` works. A no-op virtual destructor will do. (As Torsten points out, this even might be necessary in your case as you have non-POD members.)

However, from my own experience (and I have been resisting this for years!) I would strongly advise against inheritance in this particular case. Use aggregation instead. Prefer composition over inheritance? You may have to create a couple of forwarders, but the flexibility gained by this pays off (in terms of being able to later change implementations without influencing the whole system).

Think of an item that has a speed and, in addition, a text and a position, instead of being an item that somehow has speed and text and by some magic inherits the position. What if you later want an item that has speed but no known position?

To achieve your results in an aggregation scenario, define "interfaces" that constitute the contract concerning a particular feature. No need for virtual inheritance, too: The "interfaces" are just classes with only pure virtual functions. See also: What does it mean to "program to an interface"? (Another important rule if you want maintainable software.)

Example

You could define four "interfaces" (classes with only pure virtual functions): `Position`, `Speed`, `Text` and `Item`. `Item` inherits from the three former and defines no functions itself. You provide "reference implementations" for the first three interfaces. The "reference impl." for `Item` has three data members (the ref. impl. of the first three interfaces) and forwards to these implementations. Now you can use e.g. `Position` wherever you need something that has a position, without having to know what exactly it is. `dynamic_cast` works, too.

You could also define an interface `ItemBase` with no virtual methods and have `Position`, `Speed` and `Text` inherit from this interface. This will allow you to access all featurettes through the same base type and dynamically test for the availability of a subinterface. Still no need for `virtual` inheritance, I think...

Problem

I am trying to create some classes which only contain data members (no functions) but I would like them to be polymorphic - by which I mean I will be passing around the objects by a pointer to the base class, and I need the ability to `dynamic_cast` them to a specific derived type (and have the resulting value be `NULL` if the instance is not of the given type.) By way of example, I have an item: ``` struct Item { int x, y; } ``` I also have an item which moves, and another which contains text: ``` struct MovingItem: virtual public Item { int speedX, speedY; } struct TextItem: virtual public Item { std::string text; } ``` Presumably I have to use virtual inheritance above, because I also want an item that moves and has text, but I only want the one set of coordinates from the top-level `Item`: ``` struct MovingTextItem: virtual public MovingItem, virtual public TextItem { } ``` These can all be defined correctly, but when I try to `dynamic_cast` an `Item *` to see what type it is, my compiler complains that the source types aren't polymorphic. ``` void example(Item *i) { MovingTextItem *mti = dynamic_cast<MovingTextItem *>(i); // error! } ``` This would work if I reimplemented the whole thing using virtual functions instead of data members, but this seems like a waste as I never need to override anything. The only workaround I can think of is to add a `type` member to the base `Item` class, and check that instead of using `dynamic_cast`, and if it's of the correct type then use `static_cast` instead. (The drawback there being I have to know about all object types somewhere so the assigned `type` values don't conflict.) Is this the best solution, or is there another way? Clarification For arguments' sake, imagine I am writing each object type to a file. `MovingItem` goes to one file, `TextItem` goes to a different file, and `MovingTextItem` goes to both files. So having a base class which implements every interface won't work, unless I can somehow tell which interfaces are in use so they get written to the correct files.

Original source

Related problems