fornecimento de dependência através de classe base
-
19-09-2019 - |
Pergunta
Eu tenho uma lista de peças e alguns deles precisam de um ponteiro para um motor, vamos chamá-los EngineParts. O que eu quero é encontrar esses EngineParts usando RTTI e, em seguida, dar-lhes o Engine.
O problema é como projetar a EnginePart. Eu tenho duas opções aqui, descritos a seguir, e eu não sei qual escolher. Opção 1 é mais rápido porque ele não tem uma função virtual. A opção 2 é mais fácil se eu quiser Clone () do objeto porque sem dados que não precisa de uma função Clone ().
Todos os pensamentos? Talvez haja uma terceira opção?
Opção 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
}
Opção 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-se que a situação real é um pouco mais envolvidos, eu não posso usar uma solução simples como a criação de uma lista separada para EngineParts)
Graças
Solução 2
É uma pena que a resposta afirmando que 'uma parte não pode segurar o motor' é excluído porque essa era realmente a solução.
Uma vez que nem o motor completo é necessário, eu encontrei uma terceira via:
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)
}
Porque GetSomeValue () precisa de alguns parâmetros que motor não pode saber, não há nenhuma maneira que poderia "injetar" este valor como o ponteiro do motor foi injetado na opção 1 e 2. (Bem .. a menos que eu também fornecem uma getParams virtuais ()).
Isto esconde o motor da embreagem e me dá praticamente apenas uma forma de código-lo.
Outras dicas
funções virtuais em compiladores modernos (de cerca dos últimos 10 anos) são muito rápidos, especialmente para alvos máquina desktop, e que a velocidade não deve afetar o seu design.
Você ainda precisa de um método clone, independentemente, se você quiser copiar a partir de uma base de referência-a-pointer- /, como você deve permitir (desconhecido neste momento) derivado classes para copiar a si mesmos, incluindo detalhes de implementação como ponteiros vtable . (Embora se ater a um compilador / implementação, você pode tomar atalhos com base nele, e apenas re-avaliar os cada vez que você quiser usar outro compilador ou deseja atualizar seu compilador.)
que se livrar de todos os critérios que você listou, então você está de volta a não saber como escolher. Mas isso é fácil: escolher o que é mais simples para você fazer. (Que isto é, eu não posso dizer baseada deste exemplo fez-up, mas eu suspeito que é a primeira.)