Pergunta

Digamos que eu tenho um Base de Dados classe e vários Derivados classes. Existe alguma maneira de converter um objeto para uma das classes derivadas, sem a necessidade de escrever algo como isto:


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
}
...
else {
  ...
}
Foi útil?

Solução

Não faça isso.

Leia-se sobre polimorfismo. Quase todas as situações "elenco dinâmico" é um exemplo de polimorfismo lutando para ser implementado.

decisão Tudo o que você está fazendo no elenco dinâmica já foi feita. Apenas delegar o trabalho real para as subclasses.

Você deixou de fora a parte mais importante do seu exemplo. O, o trabalho polimórfica útil.

string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
   d1->doSomethingUseful();
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
   d2->doSomethingUseful();
}
...
else {
  ...
}

Se a cada implementos subclasse doSomethingUseful, tudo isso é muito mais simples. E polimórfico.

object->doSomethingUseful();

Outras dicas

Você pode usar dynamic_cast e teste para NULL, mas eu fortemente considerar refatoração do código em vez.

Se você precisa subclasse específica de manipulação, Template Method pode ser útil, mas sem saber o que você está tentando alcançar, é apenas uma vaga suposição.

Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

Eu tenho os seguintes métodos no meu tipo de ponteiro inteligente, simulando C # 'é' e 'como':

template< class Y > bool is() const throw()
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
template< class Y > Y* as() const throw()
    {return null() ? NULL : dynamic_cast< Y* >(ptr);}

Você pode fazer isso usando dynamic_cast, por exemplo:

if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
    // object points to a Derived1
    d1->foo();
}
else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
    // object points to a Derived2
    d2->bar();
}
else {
    // etc.
}

Mas, como já foi dito, o código como este pode indicar um design ruim, e geralmente você deve usar funções virtuais para implementar o comportamento polimórfico.

Normalmente, este é um sinal de uma má concepção. Por que você tem que fazer isso? Pode ser possível para redesenhar para que isso não é necessário.

O que você está tentando realizar, exatamente? Na minha experiência, coisas como esta são um sinal de design ruim. Re-avaliar a sua hierarquia de classes, porque o objetivo do projeto orientado a objetos é fazer as coisas como este desnecessário.

Seu exemplo não porta, porque o formato exato do nome () é não especificado. Você poderia tentar uma sucessão de dynamic_casts. Dynamic_cast retorna um ponteiro nulo se você converter para o tipo errado. No entanto, se você está fazendo um typeswitch como este, há algo de errado com seu projeto.

Eu acho que dynamic_cast é o caminho a percorrer, mas eu particularmente não acho que este é um projeto ruim para todas as condições possíveis porque objeto a ser fundidas pode ser algo fornecido por algum módulo de terceiros. Vamos objeto digamos foi criado por um plug-in que o autor do aplicativo não tem conhecimento de. E que plug-in particular pode criar Derived1 (sendo a versão antiga) tipo de objeto ou Derived2 (sendo a nova versão) tipo de objeto. Talvez o plug-in interface não foi projetada para fazer coisas versão específica, ele simplesmente cria o objeto para que o aplicativo deve fazer esse tipo de verificação para garantir adequada fundição / execução. Depois disso, podemos seguramente chamar object.doSomethingUsefulThatDoesNotExistInDerived1 ();

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top