обеспечение зависимости через базовый класс - PullRequest
0 голосов
/ 06 февраля 2010

У меня есть список деталей, и некоторые из них нуждаются в указателе на Engine, давайте назовем их EngineParts. Я хочу найти эти EngineParts, используя RTTI, а затем дать им Engine.

Проблема в том, как спроектировать EnginePart. У меня есть два варианта, описанных ниже, и я не знаю, какой из них выбрать. Вариант 1 быстрее, потому что у него нет виртуальной функции. Вариант 2 проще, если я хочу Clone () объекта, потому что без данных ему не нужна функция Clone ().

Есть мысли? Может быть, есть третий вариант?

Вариант 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
}

Вариант 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
}

(Обратите внимание, что реальная ситуация немного сложнее, я не могу использовать простое решение, такое как создание отдельного списка для EngineParts)

Спасибо

Ответы [ 2 ]

0 голосов
/ 07 февраля 2010

Жаль, что ответ о том, что «деталь не может удерживать двигатель», удален, потому что на самом деле это было решение.

Поскольку не нужен полный Двигатель, я нашел третий путь:


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)
}

Поскольку GetSomeValue () требуется несколько параметров, которые Engine не может знать, нет способа, которым он мог бы «внедрить» это значение, как указатель двигателя был введен в опциях 1 и 2. (Хорошо, если только я не предоставлю виртуальный GetParams ()).

Это скрывает двигатель от сцепления и дает мне почти единственный способ его кодировать.

0 голосов
/ 07 февраля 2010

Виртуальные функции в современных компиляторах (примерно за последние 10 лет) очень быстры, особенно для настольных компьютеров, и эта скорость не должна влиять на ваш дизайн.

Вам все равно нужен метод клонирования, независимо от того, хотите ли вы копировать из указателя / ссылки на базу, поскольку вы должны разрешить (пока неизвестно) производным классам копировать себя, включая детали реализации, такие как указатели vtable , (Хотя, если вы придерживаетесь одного компилятора / реализации, вы можете использовать ярлыки на его основе и просто переоценивать их каждый раз, когда вы хотите использовать другой компилятор или хотите обновить свой компилятор.)

Это избавляет от всех критериев, которые вы перечислили, поэтому вы снова не знаете, как выбрать. Но это легко: выберите тот, который проще всего сделать. (То есть, я не могу сказать, основываясь на этом вымышленном примере, но подозреваю, что это первый.)

...