views:

40

answers:

2

I have a list of Parts and some of them need a pointer to an Engine, lets call them EngineParts. What I want is to find these EngineParts using RTTI and then give them the Engine.

The problem is how to design the EnginePart. I have two options here, described below, and I don't know which one to choose. Option 1 is faster because it does not have a virtual function. Option 2 is easier if I want to Clone() the object because without data it does not need a Clone() function.

Any thoughts? Maybe there is a third option?

Option 1:


class Part;

class EnginePart : public Part {
    protected: Engine *engine
    public: void SetEngine(Engine *e) {engine = e}
};

class Clutch : public EnginePart {
    // code that uses this->engine
}

Option 2:


class Part;

class EnginePart : public Part {
    public: virtual void SetEngine(Engine *e)=0;
};

class Clutch : public EnginePart {
    private: Engine *engine;
    public: void SetEngine(Engine *e) { engine = e; }
    // code that uses this->engine
}

(Note that the actual situation is a bit more involved, I can't use a simple solution like creating a separate list for EngineParts)

Thanks

A: 

Virtual functions in modern compilers (from about the last 10 years) are very fast, especially for desktop machine targets, and that speed should not affect your design.

You still need a clone method regardless, if you want to copy from a pointer-/reference-to-base, as you must allow for (unknown at this time) derived classes to copy themselves, including implementation details like vtable pointers. (Though if you stick to one compiler/implementation, you can take shortcuts based on it, and just re-evaluate those every time you want to use another compiler or want to upgrade your compiler.)

That gets rid of all the criteria you've listed, so you're back to not knowing how to choose. But that's easy: choose the one that's simplest for you to do. (Which that is, I can't say based of this made-up example, but I suspect it's the first.)

Roger Pate
A: 

Too bad that the reply stating that 'a part cannot hold the engine' is deleted because that was actually the solution.

Since not the complete Engine is needed, I found a third way:


class Part;

class EngineSettings {
    private:
        Engine *engine
        friend class Engine;
        void SetEngine(Engine *e) {engine = e}
    public:
        Value* GetSomeValue(params) { return engine->GetSomeValue(params); }
};

class Clutch : public Part, public EngineSettings {
    // code that uses GetSomeValue(params) instead of engine->GetSomeValue(params)
}

Because GetSomeValue() needs a few params which Engine cannot know, there is no way it could "inject" this value like the engine pointer was injected in option 1 and 2. (Well.. unless I also provide a virtual GetParams()).

This hides the engine from the Clutch and gives me pretty much only one way to code it.

Eric