предоставление зависимости через базовый класс

StackOverflow https://stackoverflow.com/questions/2214679

Вопрос

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

Проблема в том, как спроектировать деталь двигателя.Здесь у меня есть два варианта, описанные ниже, и я не знаю, какой из них выбрать.Вариант 1 быстрее, потому что в нем нет виртуальной функции.Вариант 2 проще, если я хочу клонировать () объект, потому что без данных ему не нужна функция 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
}

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

Спасибо

Это было полезно?

Решение 2

Очень жаль, что ответ, в котором говорится, что "деталь не может удерживать двигатель", удален, потому что на самом деле это было решением.

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


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() нуждается в нескольких параметрах, которые движок не может знать, он никак не может "ввести" это значение, как указатель движка был введен в вариантах 1 и 2.(Ну..если только я также не предоставлю виртуальный getParams()).

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

Другие советы

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

Независимо от этого, вам все равно нужен метод clone, если вы хотите скопировать из pointer-/ reference-to-base , поскольку вы должны разрешить (неизвестным на данный момент) производным классам копировать самих себя, включая детали реализации, такие как указатели vtable.(Хотя, если вы придерживаетесь одного компилятора / реализации, вы можете использовать ярлыки на его основе и просто пересматривать их каждый раз, когда захотите использовать другой компилятор или обновить свой компилятор.)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top