views:

1278

answers:

8

I'm writing in second-person just because its easy, for you.

You are working with a game engine and really wish a particular engine class had a new method that does 'bla'. But you'd rather not spread your 'game' code into the 'engine' code.

So you could derive a new class from it with your one new method and put that code in your 'game' source directory, but maybe there's another option?

So this is probably completely illegal in the C++ language, but you thought at first, "perhaps I can add a new method to an existing class via my own header that includes the 'parent' header and some special syntax. This is possible when working with a namespace, for example..."

Assuming you can't declare methods of a class across multiple headers (and you are pretty darn sure you can't), what are the other options that support a clean divide between 'middleware/engine/library' and 'application', you wonder?

A: 

Sounds like you want Ruby mixins. Not sure there's anything close in C++. I think you have to do the inheritance.

Edit: You might be able to put a friend method in and use it like a mixin, but I think you'd start to break your encapsulation in a bad way.

Sam Hoice
Adding a friend function requires modification of the class definition itself, which defeats the purpose of the question, since you could just add the function itself there.
Greg Rogers
You might be able to add a simple non-friend non-member function in the same namespace, and this would both protect the encapsulation, and enhance your class. In fact, this is *the* way to do it in C++.
paercebal
+1  A: 

Sounds like a 'acts upon' relationship, which would not fit in an inheritance (use sparingly!).

One option would be a composition utility class that acts upon a certain instance of the 'Engine' by being instantiated with a pointer to it.

Redbeard
If the utility class contained the other class, added the functionality, and exposed the complete new interface that might work. Assuming the functionality you were adding didn't require access to class internals...
Sam Hoice
If you need access to class internals to implement your functionality, then either the originator of the class did it wrong or you are... :-) If you mean protected members, then a privately inherited class that exposes this functionality to the composition class would be a better solution.
Redbeard
A: 

You could do something COM-like, where the base class supports a QueryInterface() method which lets you ask for an interface that has that method on it. This is fairly trivial to implement in C++, you don't need COM per se.

You could also "pretend" to be a more dynamic language and have an array of callbacks as "methods" and gin up a way to call them using templates or macros and pushing 'this' onto the stack before the rest of the parameters. But it would be insane :)

Moishe
A: 

Or Categories in Objective C.

There are conceptual approaches to extending class architectures (not single classes) in C++, but it's not a casual act, and requires planning ahead of time. Sorry.

Don Wakefield
+1  A: 
  • Inheritance (as you pointed out), or
  • Use a function instead of a method, or
  • Alter the engine code itself, but isolate and manage the changes using a patch-manager like quilt or Mercurial/MQ

I don't see what's wrong with inheritance in this context though.

Menkboy
A: 

Sounds like a classic inheritance problem to me. Except I would drop the code in an "Engine Enhancements" directory & include that concept in your architecture.

Paul Nathan
+1  A: 

If the new method will be implemented using the existing public interface, then arguably it's more object oriented for it to be a separate function rather than a method. At least, Scott Meyers argues that it is.

Why? Because it gives better encapsulation. IIRC the argument goes that the class interface should define things that the object does. Helper-style functions are things that can be done with/to the object, not things that the object must do itself. So they don't belong in the class. If they are in the class, they can unnecessarily access private members and hence widen the hiding of that member and hence the number of lines of code that need to be touched if the private member changes in any way.

Of course if you want to access protected members then you must inherit. If your desired method requires per-instance state, but not access to protected members, then you can either inherit or composite according to taste - the former is usually more concise, but has certain disadvantages if the relationship isn't really "is a".

Steve Jessop
Thanks for the excellent post, runner up award!
James
+6  A: 

My only question to you is, "does your added functionality need to be a member function, or can it be a free function?" If what you want to do can be solved using the class's existing interface, then the only difference is the syntax, and you should use a free function (if you think that's "ugly", then... suck it up and move on, C++ wasn't designed for monkeypatching).

If you're trying to get at the internal guts of the class, it may be a sign that the original class is lacking in flexibility (it doesn't expose enough information for you to do what you want from the public interface). If that's the case, maybe the original class can be "completed", and you're back to putting a free function on top of it.

If absolutely none of that will work, and you just must have a member function (e.g. original class provided protected members you want to get at, and you don't have the freedom to modify the original interface)... only then resort to inheritance and member-function implementation.

For an in-depth discussion (and deconstruction of std::string'), check out this Guru of the Week "Monolith" class article.

Tom Barta
Very nice link, thank you.
James
Well, it is somewhat harsh ("monkeypatching" indeed), but quite true. +1.
paercebal