Pergunta

É possível declarar uma variável em c ++ sem instanciar isso? Eu quero fazer algo parecido com isto:

Animal a;
if( happyDay() ) 
    a( "puppies" ); //constructor call
else
    a( "toads" );

Basially, eu só quero declarar um fora da condicional assim que começa o escopo direita.

Existe alguma maneira de fazer isso sem o uso de ponteiros e alocação de a na pilha? Talvez algo inteligente com referências?

Foi útil?

Solução

Você não pode fazer isso diretamente em C ++ desde que o objeto é construído ao defini-lo com o construtor padrão.

Você poderia, no entanto, executar um construtor com parâmetros para começar com:

Animal a(getAppropriateString());

Ou você poderia realmente usar algo como o ?: operator para determinar a seqüência correta. (Update: @ Greg deu a sintaxe para este Veja essa resposta.)

Outras dicas

Você não pode declarar uma variável sem chamar um construtor. No entanto, em seu exemplo, você poderia fazer o seguinte:

Animal a(happyDay() ? "puppies" : "toads");

Você não pode usar referências aqui, pois logo que você ia ficar fora do escopo, a referência seria apontar para um objeto que seria eliminado.

Realmente, você tem duas opções aqui:

1- Vá com ponteiros:

Animal* a;
if( happyDay() ) 
    a = new Animal( "puppies" ); //constructor call
else
    a = new Animal( "toads" );

// ...
delete a;

2- Adicionar um método de inicialização de Animal:

class Animal 
{
public:
    Animal(){}
    void Init( const std::string& type )
    {
        m_type = type;
    }
private:
    std:string m_type;
};

Animal a;
if( happyDay() ) 
    a.Init( "puppies" );
else
    a.Init( "toads" );

Eu pessoalmente ir com a opção 2.

Eu prefiro a resposta de Greg, mas você também pode fazer isso:

char *AnimalType;
if( happyDay() ) 
    AnimalType = "puppies";
else
    AnimalType = "toads";
Animal a(AnimalType);

Sugiro isso porque eu tenho trabalhado lugares onde foi proibido o operador condicional. (Suspiro!) Além disso, este pode ser expandida para além duas alternativas muito facilmente.

Se você quiser evitar a coleta de lixo -. Você poderia usar um ponteiro inteligente

auto_ptr<Animal> p_a;
if ( happyDay() )
    p_a.reset(new Animal( "puppies" ) );
else
    p_a.reset(new Animal( "toads" ) );

// do stuff with p_a-> whatever.  When p_a goes out of scope, it's deleted.

Se você ainda quiser usar o. sintaxe, em vez de ->, você pode fazer isso após o código acima:

Animal& a = *p_a;

// do stuff with a. whatever

Além de resposta de Greg Hewgill, existem algumas outras opções:

Levante o corpo principal do código em uma função:

void body(Animal & a) {
    ...
}

if( happyDay() ) {
  Animal a("puppies");
  body( a );
} else {
  Animal a("toad");
  body( a );
}

(ab) uso posicionamento novo:

struct AnimalDtor {
   void *m_a;
   AnimalDtor(void *a) : m_a(a) {}
   ~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};

char animal_buf[sizeof(Animal)]; // still stack allocated

if( happyDay() )
  new (animal_buf) Animal("puppies");
else
  new (animal_buf) Animal("toad");

AnimalDtor dtor(animal_buf); // make sure the dtor still gets called

Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on

A melhor solução é usar ponteiro.

Animal a*;
if( happyDay() ) 
    a = new Animal( "puppies" ); //constructor call
else
    a = new Animal( "toads" );

Sim, você pode fazer fazer o seguinte:

Animal a;
if( happyDay() )
    a = Animal( "puppies" );
else
    a = Animal( "toads" );

Isso vai chamar os construtores corretamente.

EDIT: Esqueceu uma coisa ... Ao declarar um, você vai ter que chamar um construtor ainda, seja um construtor que não faz nada, ou ainda inicializa os valores para o que quer. portanto, esse método cria dois objetos, um na inicialização e um dentro do if.

A melhor maneira seria a criação de uma função init () da classe, tais como:

Animal a;
if( happyDay() )
    a.init( "puppies" );
else
    a.init( "toads" );

Desta forma, seria mais eficiente.

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